7

Soprattutto in Unittests usiamo questo "design pattern" che io chiamo "get classe da livello di classe"Nome del Design Pattern: ottenere classe da livello di classe

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

il metodo get_response() ottiene la classe da self non importando essa. In questo modo una sottoclasse può modificare la classe e utilizzare un diverso HttpClient.

Qual è il nome di questo (ottenere classe da livello di classe) "modello di progettazione"?

È questo un modo di "inversione del controllo" o "iniezione di dipendenza"?

risposta

4

Credo che questo abbia lo stesso scopo del semplice polimorfismo implementato usando la sintassi specifica di Python. Invece di avere un metodo virtuale che restituisce una nuova istanza, si ha il tipo di istanza memorizzato come "una variabile sovrascrivibile" in una classe/sottoclasse.

Questo può essere riscritta come un metodo virtuale (mi dispiace non sono fluente in Python quindi questo è solo pseudocodice)

virtual HttpClient GetClient() 
    return new FrameworkHttpClient() 

poi nella sottoclasse, si modifica l'implementazione del metodo per restituire un tipo diverso :

override HttpClient GetClient() 
    return new MyHttpClient() 

Se si desidera chiamare questo un modello, direi che è simile a Strategy GoF pattern. Nel tuo caso particolare, l'algoritmo che viene sottratto è la creazione della particolare implementazione di HttpClient.

E dopo un secondo ripensamento - come hai affermato, in effetti questo può essere considerato un esempio di IoC.

1

Io non sono esattamente un modello di progettazione "Guru", ma per me sembra un bit come il modello Metodo modello. Stai definendo lo "scheletro" del metodo get_response nella tua classe base e lasciando un passo (che definisce quale classe usare) nelle sottoclassi.

Se questo può essere considerato il modello di modello, è un esempio di inversione del controllo.

5

Il tuo codice è molto simile a Factory method pattern. L'unica differenza è che la tua variante utilizza una variabile di classe factory invece del metodo factory.

+0

grazie. Sì, lo schema del metodo di produzione è molto simile. – guettli

1

Si desidera consentire alle sottoclassi di decidere quale classe istanziare.

Questo è ciò che la factory method pattern offre già:

Definire un'interfaccia per la creazione di un oggetto, ma cerchiamo le classi che implementano l'interfaccia decidere quale classe istanziare. Il metodo Factory consente a una classe di differire l'istanzazione alle sottoclassi. (GoF)

Risolvete lo stesso problema sostituendo una variabile della classe genitore. Funziona, ma la soluzione ha almeno due inconvenienti (rispetto al modello classico):

  1. si introduce un accoppiamento temporale (design odore). Il cliente deve chiamare le istruzioni nel giusto ordine. (prima inizializzare lo HttpClient quindi invocare get_response)
  2. il test case non è immutabile. Le classi immutabili sono le più semplici di quelle mutevoli. E secondo me il test dovrebbe essere sempre semplice.
+0

Rispondere a "1. si introduce un accoppiamento temporale (odore di progetto). Il cliente deve chiamare le istruzioni nell'ordine corretto." Ciò non viene introdotto dal modello di progettazione "metodo di fabbrica". Prima che HttpClient fosse importato. Una sottoclasse non può utilizzare un HttpClient diverso. Rispondi a "2. il tuo test case non è immutabile". Per favore, spiegamelo. Non vedo come fosse immutabile prima di usare lo schema del metodo di fabbrica. – guettli

+0

@guetti Non capisco la tua prima risposta. Il mio punto è che è immutabile se si utilizza il modello di metodo di fabbrica. – gontard

+1

'HttpClient' è inizializzato a livello di classe, non in' __init __() '. * Non è possibile * chiamare le cose nell'ordine sbagliato, poiché la classe deve essere completamente inizializzata prima di poter essere istanziata. – Kevin