Я мог бы иметь класс VegetableManager (или что-то еще), где есть метод загрузки, но означает ли это на самом деле менее повторяющийся код?Затем на каждом экране я должен создать объект VegetableManager и в любом случае вызвать его метод загрузки.
Смысл этого не в эффективности (то есть в производительности).Суть в том, чтобы инкапсулировать детали загрузки этих данных в один изолированный объект.Скажем, например, что ваш сайт становится действительно большим, и вы решили переместить хранилище данных в базу данных для масштабируемости и производительности.В существующем коде, который вы описали, вам придется пройти через каждый пользовательский элемент управления или страницу и изменить логику метода загрузки.В лучшем случае это боль, а в худшем - вы пропускаете или неправильно копируете.Если логика инкапсулирована в выделенном объекте, единственная обязанность которого состоит в том, чтобы знать, как загрузить данные откуда-то, то вам нужно внести изменение только один раз.
код за пользовательским контролем:
protected void Page_Load(object sender, EventArgs e) {
var veggieManager = new VegetableManager();
VeggieListControl.DataSource = veggieManager.GetAll();
VeggieListControl.DataBind();
}
VegetableManager.cs:
public class VegetableManager {
private static Collection<Vegetable> _veggies;
private static object _veggieLock;
public ReadOnlyCollection<Vegetable> GetAll() {
if (_veggies == null) {
lock(_veggieLock) { //synchronize access to shared data
if (_veggies == null) { // double-checked lock
// logic to load the data into _veggies
}
}
}
return new ReadOnlyCollection(_veggies);
}
public void Add(Vegetable veggie) {
GetAll(); // call this to ensure that the data is loaded into _veggies
lock(_veggieLock) { //synchronize access to shared data
_veggies.Add(veggie);
// logic to write out the updated list of _veggies to the file
}
}
}
Поскольку _veggies
равен static
, в памяти имеется только одна коллекция овощей, несмотря на тот факт, что несколько абонентов будут создавать экземпляр VegetableManager
.Но поскольку он статический, если у вас есть многопоточное приложение (например, веб-сайт), вы должны синхронизировать доступ к этому полю во всех потоках (отсюда lock
s).
Это верхушка айсбергас точки зрения хорошей объектной ориентации.Я рекомендую просмотреть SOLID принципы UncleBob и Domain-Driven Design ( бесплатная электронная книга ).
Итак, да, вычто-то повторяете, но все, что вы повторяете, - это вызов метода , и это нормально для повторения.DRY означает смягчение дублирования «логического» кода, то есть принятия решений и алгоритмов;простые вызовы методов не подпадают под это.Однако, если вы хотите, вы можете объединить логику в базовый класс, сделав это, эффективно изолируя пользовательские элементы управления от необходимости знать о VegetableManager, хотя я думаю, что это излишняя ориентация на объект или ООО: -)
public abstract class FoodUserControl : UserControl {
protected List<Vegetable> GetVeggies() {
return new VegetableManager().GetAll();
}
}
Тогда ваши фактические элементы управления будут получены из этого, а не из UserControl.
Обновление
Стремительная загрузка VegetableManager.cs:
public class VegetableManager {
private static Collection<Vegetable> _veggies;
private static object _veggieLock;
static VegetableManager() {
// logic to load veggies from file
}
public ReadOnlyCollection<Vegetable> GetAll() {
return new ReadOnlyCollection(_veggies);
}
public void Add(Vegetable veggie) {
lock(_veggieLock) { //synchronize access to shared data
_veggies.Add(veggie);
// logic to write out the updated list of _veggies to the file
}
}
}
Обратите внимание, что эта загружаемая версия не требует двойной проверки блокировки кода загрузки в конструкторе.Также обратите внимание, что код загрузки находится в конструкторе static
, поскольку этот код инициализирует поле static
(в противном случае вы будете перезагружать данные из файла каждой конструкции в одно и то же общее поле static
).Поскольку овощи загружаются очень быстро, вам не нужно загружать их в GetAll или Add.