假设我有多个用户控件,每个用户控件都在一个Tabitem中,在一个窗口中。
例如,假设这是一个食物收集应用程序。然后,我们有水果,蔬菜和小吃的标签。每个选项卡将显示该主题的食物列表,并允许用户在每个部分中添加,删除,修改食物。食物存储在单独的文本文件中,即Fruit.txt,Vegetable.txt,Snack.txt
实际的文本文件可能看起来像这样(vegetable.txt):
Name Carbs Fat
Eggplant 2 1.1
Cucumber 3 0.5
etc
现在这是一个很大的列表,并且有一种加载方法,可以将所有蔬菜拉出一个列表
我的问题是这个loadVegetables方法在文件后面的代码中,并且我最终在整个地方重复此加载方法,因为我还有其他屏幕,如ReviewAllFood,AddVegetable等,以及所有其他加载方法水果和小吃。
这更多是一个设计问题,我想知道如何设置它以免重复此代码。在加载方法所在的位置,我可以有一个VegetableManager(或其他类)类,但这实际上意味着较少的重复代码吗?然后,在每个屏幕中,我必须创建VegetableManager的对象,并始终调用其load方法。因此,我认为效率并没有更好,但是我确实实现了更好的设计。
我想我在这里错过了一些东西。自从我研究了内聚力和耦合以来已经有一段时间了,我认为我现在将自己与这些概念混淆了。欣赏是否有人可以针对这种情况建议设计并解释为什么选择它,以及为什么它比我现在做的更好。
谢谢阅读。
最佳答案
我可以有一个VegetableManager(或者
东西)类在哪里加载方法
是,但这实际上意味着更少
重复的代码?然后在每个屏幕中
必须创建对象
VegetableManager并调用其负载
反正方法。
这样做的重点不是效率(即性能)。关键是封装将数据加载到单个隔离对象中的详细信息。假设您的站点很大,您决定将数据存储移至数据库以实现可伸缩性和性能。在您描述的现有代码中,您将必须遍历每个用户控件或页面并更改load方法的逻辑。最好的情况下,这是一种痛苦,而最坏的情况下,您会错过一些或错误地粘贴粘贴。如果逻辑被封装到一个专用对象中,其唯一职责是知道如何从某个位置加载数据,那么您只需进行一次更改即可。
用户控件的代码背后:
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
)。就良好的对象定向而言,这是冰山一角。我建议仔细阅读UncleBob's SOLID principles和Domain-Driven Design(free e-book)。
因此,是的,您正在重复某件事,但是您重复的只是一个方法调用,可以重复。 DRY意味着减轻“逻辑”代码的重复,即决策和算法;简单的方法调用不属于此范围。但是,如果您愿意,您可以将逻辑合并到基类中,从而有效地将用户控件与对VegetableManager的了解隔离开来,尽管我认为这是面向对象的过大杀伤力,或OOO :-)
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。关于c# - 设计问题-OO食品应用,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/2285366/