Open closed principle 开闭原则,重构

Open closed principle 开闭原则,重构,open-closed-principle,Open Closed Principle,我正在尝试将OCP应用到一个代码片段中,我有一个代码片段,它的当前状态非常糟糕,但我觉得我并没有走到最后 当前代码: public abstract class SomeObject {} public class SpecificObject1 : SomeObject {} public class SpecificObject2 : SomeObject {} // Smelly code public class Model { public void Store(SomeO

我正在尝试将OCP应用到一个代码片段中,我有一个代码片段,它的当前状态非常糟糕,但我觉得我并没有走到最后

当前代码:

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,它的责任是它不知道如何存储自己

如果出现某个对象的新实现,则缺少谁的存储实现 由于模型类中的异常存储方法,我将得到一个运行时错误,它也感觉像一种代码味道

这是因为调用代码将以

IEnumerable<SomeObject> sequence;
IEnumerable序列;
我不知道序列对象的具体类型


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

我正在介绍的模式试图为特定对象注册处理程序。对于可能出现的每种类型的对象,都必须有处理程序registerd。如果没有处理程序可以处理它,则会引发异常

您可以从您的程序集或其他程序集动态加载处理程序(实现
IHandler
)并实例化和添加它们。因此,为实现
SomeObject
的任何类型创建处理程序类就足够了

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;
        }
    }
}
公共接口IHandler{
bool TryHandle(SomeObject o);//返回true
}
公共类模型
{
私有列表_Handlers=新列表();
//注册一个新的处理程序
公共无效登记管理器(IHandler h){
_添加(h);
}
//这将尝试通过让所有处理程序尝试存储对象来存储对象
公共空存储(SomeObject o){
foreach(变量h在_处理程序中){
如果(h.Store(o))返回;
}
//没有处理程序能够处理该类型
抛出新异常();
}
}
公共类特定的1处理程序:IHandler
{
公共布尔句柄(SomeObject o){
如果(o是SpecificType1){
/*商店*/
return true;//我们处理了这个对象
}否则{
//我们没有资格
返回false;
}
}
}

我相信这会符合你的需要。(顺便说一句,我不知道这个模式是否有名字,如果有,我会很高兴知道。)

如果你能展示哪些存储方法有不同的功能会更好。在
SomeObject
中有一个虚拟的
Store
函数真的那么糟糕吗?()您可能希望实现一种策略模式,因为您的代码不太臭,违反了单一责任原则。@tafa:存储方法的不同之处在于每个SomeObject将数据存储在不同的表/类中,这些表/类具有不同的列/字段。@Andreas Brinck IMHO模型不应该是贫乏的,但它也不应该承担不属于它的责任。模型对象应该具有域功能。这是一种策略和/或责任链。