2010-04-22 64 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