使用泛型实现开放封闭原则

Posted

技术标签:

【中文标题】使用泛型实现开放封闭原则【英文标题】:Implementing open closed principle using generics 【发布时间】:2016-10-05 08:10:46 【问题描述】:

我是使用 SOLID 的新手,所以请原谅我缺乏正确的术语,请纠正我,如果需要,我希望学习 :-)

我正在升级一个库,并希望使用 Open Closed 原则,出于可扩展性的原因而无需修改提供程序。

库的目的是提供基于视图类型的模块列表。根据类型,检索模块的查询和条件是不同的。以下是当前代码的简化版本:

public class ModuleProvider

    public List<ITreeNode> GetModules(ViewType viewType)
    
        switch (viewType)
        
            case ViewType.Classes
                //build query here that returns List<TreeNode> for classes
                return modules;
            case ViewType.Queries
                //build query here that returns List<TreeNode> for queries
                return modules;
        
    

我已经读过,在上面的例子中使用 switch 语句是不好的。我明白为什么,因为如果我要添加新的 ViewType,GetModules 将需要更改。

我想我必须创建一个具有 GetModules 函数的接口,然后为每个接口创建一个类,即 QueryModules 和 ClassModules 类以返回特定列表。但是,我不知道上面的提供者需要如何改变才能支持这一点?我认为我需要为此使用泛型是正确的吗?

public interface IModuleProvider

    List<ITreeNode> GetModules();


public class QueryModuleProvider : IModuleProvider

    public List<ITreeNode> GetModules()
    
        return new List<ITreeNode>()  new TreeNode()  Type = "Query Module"  ;
    


public class ClassModuleProvider : IModuleProvider

    public List<ITreeNode> GetModules()
    
        return new List<ITreeNode>() new TreeNode()  Type = "Class Module";
    

我在正确的轨道上吗?非常感谢 *** 的聪明成员提供的任何帮助。

谢谢

【问题讨论】:

第二个代码 sn-p 中未涵盖的您需要什么? 这种方法应该很明显,它不一样 - 您已将 List&lt;ITreeNode&gt; GetModules(ViewType viewType) 更改为 List&lt;ITreeNode&gt; GetModules()。您现在不是要求一个班级提供模块,而是需要在两个班级之间做出决定——这正是您开始时的情况。这是一个“先有鸡还是先有蛋”的问题。 查找策略模式。这通常是 switch 语句的答案 【参考方案1】:

这种方法应该很明显,它不一样 - 您已将 List&lt;ITreeNode&gt; GetModules(ViewType viewType) 更改为 List&lt;ITreeNode&gt; GetModules()。您现在不是要求一个班级提供模块,而是需要在两个班级之间做出决定——这正是您开始时的情况。这是一个“先有鸡还是先有蛋”的问题。

相反,您应该注入一种动态决定如何构建树节点的方法。

这是一种方法:

public class ModuleProvider

    private Dictionary<ViewType, Func<List<ITreeNode>>> _factory;

    public ModuleProvider(Dictionary<ViewType, Func<List<ITreeNode>>> factory)
    
        _factory = factory;
    

    public List<ITreeNode> GetModules(ViewType viewType)
    
        return _factory[viewType]();
    

当您创建 ModuleProvider 时,您将在工厂字典中注入以生成树节点。您可以通过多种方式构建该字典,而无需重新编译程序集。

【讨论】:

以上是关于使用泛型实现开放封闭原则的主要内容,如果未能解决你的问题,请参考以下文章

深入浅出设计模式——开放封闭原则

设计模式--开放封闭原则

面向对象原则之一 开放封闭原则(开闭原则)

Charpter04 开放-封闭原则

C#重新抽象是不是违反了开放/封闭原则?

面象对象设计6大原则之二:开放封闭原则