假设我有多个用户控件,每个用户控件都在一个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
    }
  }
}


因为_veggiesstatic,所以尽管多个调用者将实例化VegetableManager,但内存中只有一个蔬菜集合。但是因为它是静态的,所以如果您有多线程应用程序(例如网站),则必须跨所有线程同步对该字段的访问(因此lock)。

就良好的对象定向而言,这是冰山一角。我建议仔细阅读UncleBob's SOLID principlesDomain-Driven Designfree 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/

10-10 02:02