Il modello di strategia prevede la modifica di ogni sottoclasse?

2

Considera una percentuale eccellente diAnimal, ereditata da più sottoclassi ( Dog / Bird ). Nella loro istanziazione, gli oggetti hanno il loro stato locale e amp; comportamento:

wiki dice:

The strategy pattern

  • defines a family of algorithms,
  • encapsulates each algorithm, and
  • makes the algorithms interchangeable within that family.

Se un requisito richiede di aggiungere un nuovo comportamento ( fly() ) in super classe Animal , quindi utilizzare il modello di strategia, per creare una nuova famiglia di algoritmi ( CantFly / ItFly ) e incapsulare questi algoritmi in setFlyingAbility() / tryToFly() , per ottenere modifiche minime al codice nella gerarchia di classi esistente, con le seguenti modifiche:

doveItFylseCantFlysonofamigliedialgoritmipernuovocomportamento(fly)chevengonoutilizzatidallesottoclassi(Dog/Bird)inmodointercambiabile,conlemodifichealcodicesotto

L'associazione di tipo Composizione , in fase cruciale, sta contribuendo ad aggiungere un nuovo comportamento in super classe riducendo al minimo le modifiche al codice nella relazione super / sottocategoria, mostrata sotto,

class Animal{
    ....
    Flys flyingType;
    ....
    public String tryToFly(){
       return flyingType.fly();
    }
    public void setFlyingAbility(Flys newFlyType){
      flyingType = newFlyType;
    }
}

Domanda:

Per aggiungere un nuovo comportamento ( fly() ) in super classe ( Animal ), il modello di strategia comporta la modifica di ogni costruttore di sottoclasse ( Dog / Bird )? La modifica della sottoclasse può essere evitata?

    
posta user1787812 23.09.2017 - 20:45
fonte

2 risposte

1

La tua implementazione del modello di strategia va bene, ma non penso che il tuo esempio sia una buona illustrazione del problema che Strategy Pattern sta risolvendo.

Considera l'ordinamento. Data una serie di elementi comparabili, scegliamo tra molti diversi algoritmi di ordinamento (o "strategie"). Un caso di uso comune del modello di strategia viene utilizzato per eseguire gli algoritmi in parallelo, ad esempio, fino alla conclusione del primo. I database hanno un approccio simile alla ricerca del metodo più efficiente per eseguire una query, durante la fase di ottimizzazione.

La tua analogia OO con Cane / Uccello che eredita da Animale non si adatta perfettamente a questo, dal mio punto di vista, perché la strategia di fly() che scegli dipende dal fatto che l'input sia un cane o un uccello.

Una soluzione migliore per la tua situazione è l'idea di una funzione virtuale. In tal caso, la classe base Animal dichiara la firma della funzione e rimanda l'implementazione alle classi ereditarie.

    
risposta data 23.09.2017 - 22:01
fonte
0

Il "modello di strategia" è una falsa pista qui!

Esiste una gerarchia di classi esistente (di animali) e si tenta di rendere il codice più SOLIDO (in questo caso specificamente SRP e OCP conformi). Quindi il refactoring causa la necessità di toccare ogni costruttore nella gerarchia - ma è abbastanza normale quando si effettua una gerarchia di classi non solida più SOLID e ha assolutamente nothing in l'approccio specifico qui è "Strategia". Il vero motivo è che il refactoring di una base di codice più complessa richiede più sforzo che rifattorizzare uno più semplice - questo è IMHO non molto sorprendente!

Il modello "Strategia" richiede sempre uno o più punti nel programma in cui la sottoclasse della strategia specifica deve essere scelta, o cambiata (forse cambia in runtime, forse no). Questo fa parte della logica aziendale e la posizione "corretta" dipende dal caso. Quando viene introdotto in un contesto semplice (come una classe di test senza una gerarchia di classi), ci sono tipicamente meno cose da cambiare rispetto a quando viene introdotto in un contesto più complesso come una gerarchia di classi. Tuttavia, la ragione di ciò è la complessità del contesto , non il modello.

In questo specifico esempio, è logico prendere la decisione sulla strategia nel costruttore dei diversi animali - l'associazione Dog - CantFly , Bird - ItFlys deve essere da qualche parte, e poiché la strategia corretta può essere scelta dal tipo di animale, per conoscenza generale, e non cambierà durante la vita di ogni oggetto, il costruttore non è il posto peggiore per implementarlo.

Quindi sì, rendendo questo codice più SOLIDO comporta la modifica dei costruttori nel momento in cui introduci il pattern nel codice , niente di meno, non di più (nel codice reale, probabilmente dovrai refactoring di più cose nella gerarchia delle classi Animali per introdurre il modello). Nota il punto su cui tali refactoring non devono evitare le modifiche al codice prima che è stato introdotto, ma dopo .

    
risposta data 24.09.2017 - 09:22
fonte