2010-04-22 71 views
2

我想将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,它的可重复性不是如何知道存储自己。

如果一个新的实施SomeObject走来谁的存储实现丢失 我会得到运行误差由于Model类在商店的方法外,还感觉就像一个代码味道。

这是因为调用代码将在

IEnumerable<SomeObject> sequence; 

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

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

+1

如果您可以显示Store方法的不同之处,将会好得多。 – tafa 2010-04-22 10:56:15

+0

在SomeObject中有一个虚拟的'Store'函数真的会这么糟糕吗? (http://www.martinfowler.com/bliki/AnemicDomainModel.html) – 2010-04-22 11:01:15

+0

您可能希望实施一种策略模式,因为您的代码不会太臭,违反了单一责任原则。 – Kane 2010-04-22 11:07:00

回答

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; 
     } 
    } 
} 

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

+0

这是恕我直言的一种战略和/或责任链。 – 2010-04-22 22:04:56