开闭原则,重构

Posted

技术标签:

【中文标题】开闭原则,重构【英文标题】:Open closed principle, refactoring 【发布时间】:2010-04-22 10:45:41 【问题描述】:

我正在尝试将 OCP 应用到代码 sn-p 我有它的当前状态真的很臭,但我觉得我没有走到最后。

当前代码:

public abstract class SomeObject


public class SpecificObject1 : SomeObject


public class SpecificObject2 : SomeObject



// Smelly code
public class Model

  public void Store(SomeObject someObject)
  
    if (someObject is SpecificObject1)
    
    else if (someObject is SpecificObject2)
    
  

真的很丑,我的新方法是这样的:

// No so smelly code
public class Model

  public void Store(SomeObject someObject)
  
    throw new Expception("Not allowed!");
  

  public void Store(SpecificObject1 someObject)
  

  public void Store(SpecificObject2 someObject)
  


当出现新的 SomeObject 类型时,我必须实现该特定对象 已存储,这将破坏 OCP,因为我需要更改模型类。

将存储逻辑移动到 SomeObject 也感觉不对,因为那我会违反 SRP (?),因为在这种情况下 SomeObject 几乎就像一个 DTO,它的责任是它不知道如何存储自己。

如果出现 SomeObject 的新实现,则缺少谁的 store 实现 由于 Model 类的 Store 方法中的异常,我会收到 runtime 错误,感觉也像代码异味。

这是因为调用代码的形式是

IEnumerable<SomeObject> sequence;

我不会知道序列对象的具体类型。

我似乎无法理解 OCP 的概念。任何人都有任何具体的示例或链接,而不仅仅是一些汽车/水果示例?

【问题讨论】:

如果你能展示Store方法的不同之处会更好。 SomeObject 中有一个虚拟的Store 函数真的会很糟糕吗? (martinfowler.com/bliki/AnemicDomainModel.html) 你可能想要实现一个策略模式,因为你不那么臭的代码违反了单一责任原则。 @tafa:存储方法的区别在于每个 SomeObject 将数据存储在具有不同列/字段的不同表/类中。 @Andreas Brinck 恕我直言,模型不应该是贫血的,但它也不应该承担不属于它的责任。恕我直言,模型对象应该具有域功能。 【参考方案1】:

我提出的模式是尝试为特定对象注册处理程序。必须为可能发生的每种类型的对象注册处理程序。如果没有处理程序可以处理它,则会引发异常。

您可以从您的或从其他程序集动态加载处理程序(实现IHandler 的所有内容)并实例化并添加注册它们。因此,为实现@ 的任何类型创建处理程序类就足够了987654322@.

public interface IHandler 
    bool TryHandle (SomeObject o); // return true iff handled


public class Model

    private List<SIandler> _Handlers = new List<IHandlers>();

    // registers a new handler
    public void RegisterHandler (IHandler h) 
        _Handlers.Add(h);
    

    // this tries to store an object by letting all handlers attempts to store
    public void Store (SomeObject o) 
        foreach (var h in _Handlers) 
            if (h.Store(o)) return;
        

        // no handler was able to handle the type
        throw new Exception();
    


public class Specific1Handler: IHandler

    public bool Handle (SomeObject o) 
        if (o is SpecificType1) 
            /* store... */
            return true; // we handled this object
         else 
            // we're not qualified
            return false;
        
    

我相信这会满足您的需求。 (顺便说一下,我不知道这个模式有没有名字,如果有的话会很高兴学习。)

【讨论】:

恕我直言,这是一种战略和/或责任链。

以上是关于开闭原则,重构的主要内容,如果未能解决你的问题,请参考以下文章

设计模式六大原则:开闭原则

设计模式六大原则:开闭原则

开闭原则

11设计模式六大原则——开闭原则

设计模式七大原则开闭原则

[转]设计模式六大原则[6]:开闭原则