7

Zwłaszcza w unittests używamy ten „wzorzec projektowania” Wzywam „dostać klasę od poziomu klasy”Nazwa wzorzec projektowy: uzyskać klasę od poziomu klasy

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() 
     ... 

Sposób get_response() dostaje klasę z self nie importując go. W ten sposób podklasa może zmodyfikować klasę i użyć innego HttpClient.

Jaka jest nazwa tego (uzyskaj klasę od poziomu klasy) "wzorca projektowego"?

Czy jest to metoda "odwrócenia kontroli" lub "wstrzyknięcia zależności"?

Odpowiedz

4

Wierzę, że ma to ten sam cel, co zwykły polimorfizm zaimplementowany przy użyciu specyficznej dla Pythona składni. Zamiast wirtualnej metody zwracania nowych instancji, typ instancji jest przechowywany jako "zmienna podlegająca zmianie" w klasie/podklasie.

To może być zapisane jako metoda wirtualnego (przepraszam nie jestem biegły w Pythonie, więc jest to tylko pseudokod)

virtual HttpClient GetClient() 
    return new FrameworkHttpClient() 

następnie w podklasie zmienić realizację sposobu, aby powrócić inny typ :

override HttpClient GetClient() 
    return new MyHttpClient() 

Jeśli chcesz wywołać ten wzór, powiedziałbym, że jest podobny do Strategy GoF pattern. W twoim przypadku usunięty algorytm jest tworzeniem konkretnej implementacji HttpClient.

I po drugiej myśli - tak jak stwierdzono, rzeczywiście można to traktować jako przykład IoC.

1

Nie jestem dokładnie wzorcem "Guru", ale dla mnie wygląda on jak bit, podobnie jak wzór metody szablonów. Definiujesz "szkielet" metody get_response w swojej klasie bazowej i pozostawiasz jeden krok (definiując, której klasy użyć) do podklas.

Jeśli można to uznać za wzór szablonu, jest to przykład odwrócenia kontroli.

5

Twój kod jest bardzo podobny do Factory method pattern. Jedyna różnica polega na tym, że twój wariant używa zmiennej fabrycznej zamiast metody fabrycznej.

+0

dziękuję. Tak, fabryczny wzór metody wygląda bardzo podobnie. – guettli

1

Chcesz, aby podklasy decydowały, którą klasę utworzyć.

To właśnie factory method pattern już oferuje:

zdefiniować interfejs do tworzenia obiektu, ale niech klasy, które implementują interfejs zdecydować jakiej klasy instancji. Metoda Factory pozwala klasie odroczyć instancję podklasom. (GoF)

Twoje rozwiązanie tego samego problemu poprzez zastąpienie zmiennej klasy nadrzędnej. To działa, ale rozwiązanie ma przynajmniej dwie wady (w porównaniu do klasycznego wzorca):

  1. przedstawisz sprzęgło czasowy (projekt zapach). Klient musi wywołać instrukcje we właściwej kolejności. (najpierw zainicjuj HttpClient następnie wywołaj get_response)
  2. Twój przypadek testowy nie jest niezmienny. Klasy niezmienne są najprostsze od tych zmiennych. I moim zdaniem test powinien zawsze być prosty.
+0

Odpowiedz na "1. wprowadzasz czasowe sprzężenie (projektowany zapach) Klient musi wywołać instrukcje we właściwej kolejności." Nie jest to wprowadzane przez wzorzec projektowy "metoda fabryczna". Przed zaimportowaniem HttpClient. Podklasa nie może używać innego HttpClient. Odpowiedz na "2. Twój przypadek testowy nie jest niezmienny." Proszę to wyjaśnić. Nie widzę, jak to było niezmienne przed użyciem wzoru metody fabrycznej. – guettli

+0

@guetti Nie rozumiem twojej pierwszej odpowiedzi. Chodzi mi o to, że jest niezmienny, jeśli użyjesz fabrycznego wzoru metody. – gontard

+1

'HttpClient' jest inicjowany na poziomie klasy, a nie w' __init __() '. Wywołanie rzeczy w niewłaściwej kolejności * nie jest możliwe *, ponieważ klasa musi zostać w pełni zainicjowana, zanim będzie można utworzyć instancję. – Kevin

Powiązane problemy