7

特別是在單元測試,我們使用這個「設計模式」我叫設計模式的名稱:得到一流水平一流

framworktest.py「從一流水平得到類」:

class FrameWorkHttpClient(object): 
    .... 

class FrameWorkTestCase(unittest.TestCase): 

    # Subclass can control the class which gets used in get_response() 
    HttpClient=FrameWorkHttpClient 

    def get_response(self, url): 
     client=self.HttpClient() 
     return client.get(url) 

mytest.py :

class MyHttpClient(FrameWorkHttpClient): 
    .... 

class MyTestCase(FrameWorkTestCase): 
    HttpClient=MyHttpClient 

    def test_something(self): 
     response=self.get_response() 
     ... 

get_response()通過導入它從self獲取類沒有的方法。這樣子類可以修改類並使用不同的HttpClient

這是什麼名稱(從班級級別獲得班級)「設計模式」?

這是「控制反轉」還是「依賴注入」?

回答

4

我相信這與使用Python特定語法實現的簡單多態性具有相同的目的。虛擬方法不是返回一個新的實例,而是在類/子類中將實例類型存儲爲「可重寫的變量」。

這可以被改寫爲虛方法(對不起,我不流利在Python所以這只是僞代碼)

virtual HttpClient GetClient() 
    return new FrameworkHttpClient() 

然後在子類中,你改變了方法的實現返回不同的類型:

override HttpClient GetClient() 
    return new MyHttpClient() 

如果你想稱這種模式,我會說它類似於Strategy GoF pattern。在你的具體情況下,被抽象出來的算法是創建特定的HttpClient實現。

經過第二次思考 - 正如您所說的那樣,事實上這可以看作是一個IoC示例。

1

我不完全是設計模式'大師',但對我來說它看起來像模板方法模式。您正在基類中定義get_response方法的「框架」,並向子類留下一步(定義要使用哪個類)。

如果這可以被認爲是模板模式,它​​是控制反轉的一個例子。

5

您的代碼與Factory method pattern非常相似。唯一的區別是您的變體使用工廠類變量而不是工廠方法。

+0

謝謝。是的,工廠方法模式看起來非常相似。 – guettli

1

你想讓子類決定實例化哪個類。

這就是factory method pattern已經提供:

定義的界面,用於創建一個對象,但讓實現該接口的類決定將哪一個類實例。 Factory方法讓類將實例化推遲到子類。 (GoF)

您通過替換父類的變量解決同樣的問題。 它的工作原理,但您的解決方案至少有兩個缺點(相較於經典模式):

  1. 你介紹一個時間耦合(設計氣味)。客戶必須按照正確的順序調用說明。 (首先初始化HttpClient然後調用get_response
  2. 你的測試用例不是不可變的。不可變的類比可變的類最簡單。在我看來,測試應該總是很簡單。
+0

回覆「1.您引入了暫時性耦合(設計異味),客戶必須按照正確的順序調用說明。」這不是由設計模式「工廠方法」引入的。在導入HttpClient之前。一個子類不能使用不同的HttpClient。回覆「2.你的測試用例不是不可變的」。請解釋一下。在使用工廠方法模式之前,我沒有看到它是不可變的。 – guettli

+0

@guetti我不明白你的第一個答覆。我的觀點是,如果你使用工廠方法模式,它是不可變的。 – gontard

+1

'HttpClient'在類級初始化,而不是'__init __()'。 *不可能*以錯誤的順序調用事物,因爲在實例化之前,類必須完全初始化。 – Kevin