我正在尝试将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因为我需要改变Model类。
将商店逻辑移动到SomeObject也感觉不对,因为我会违反SRP(?),因为在这种情况下,SomeObject几乎就像一个DTO,它的重要性不是如何知道存储自己。
如果SomeObject的新实现出现了缺少哪个商店实现 由于Model类中的Store方法异常,我会得到运行时错误,它也感觉像代码味道。
这是因为调用代码将采用
的形式IEnumerable<SomeObject> sequence;
我不知道序列对象的具体类型。
我似乎无法掌握OCP概念。任何人都有任何具体的例子或链接,而不仅仅是一些汽车/水果的例子?
答案 0 :(得分:1)
我提出的模式试图为特定对象注册处理程序。必须为可能发生的每种类型的对象注册处理程序。如果没有处理程序可以处理它,则抛出异常。
您可以从您或其他程序集动态加载处理程序(实现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;
}
}
}
我相信这符合您的需求。 (顺便说一下,我不知道这个模式是否有名字,如果有的话会很高兴。)