Qual è la differenza tra il metodo modello e i modelli di strategia?


161

Qualcuno può spiegarmi qual è la differenza tra il modello di metodo del modello e il modello di strategia?

Per quanto ne so, sono uguali al 99% - l'unica differenza è che il modello di metodo del modello ha una classe astratta come classe base mentre la classe strategia utilizza un'interfaccia implementata da ogni classe strategica concreta.

Tuttavia, per quanto riguarda il cliente , vengono consumati esattamente allo stesso modo: è corretto?


2
Questo post in SO ha una risposta migliore per la stessa domanda: stackoverflow.com/questions/464524/...
Gob00st

12
La domanda a cui gob00st è collegata è la differenza tra strategia e bridge. Non è affatto la risposta a questa domanda.
bluekey il

Risposte:


135

La differenza principale tra i due è quando viene scelto l'algoritmo concreto.

Con il metodo di modello Template questo avviene a tempo di compilazione dal sottoclasse il modello. Ogni sottoclasse fornisce un diverso algoritmo concreto implementando i metodi astratti del modello. Quando un client richiama i metodi dell'interfaccia esterna del modello, il modello chiama i suoi metodi astratti (la sua interfaccia interna) come richiesto per invocare l'algoritmo.

class ConcreteAlgorithm : AbstractTemplate
{
    void DoAlgorithm(int datum) {...}
}

class AbstractTemplate
{
    void run(int datum) { DoAlgorithm(datum); }

    virtual void DoAlgorithm() = 0; // abstract
}

Al contrario, il modello di strategia consente di scegliere un algoritmo in fase di esecuzione per contenimento . Gli algoritmi concreti sono implementati da classi o funzioni separate che vengono passate alla strategia come parametro per il suo costruttore o per un metodo setter. L'algoritmo scelto per questo parametro può variare in modo dinamico in base allo stato o agli input del programma.

class ConcreteAlgorithm : IAlgorithm
{
    void DoAlgorithm(int datum) {...}
}

class Strategy
{
    Strategy(IAlgorithm algo) {...}

    void run(int datum) { this->algo.DoAlgorithm(datum); }
}

In sintesi:

  • Modello del metodo modello: selezione dell'algoritmo in fase di compilazione per sottoclasse
  • Modello di strategia: selezione dell'algoritmo di runtime per contenimento

47
Entrambi i modelli supportano la selezione runtime dell'algoritmo utilizzato (per Metodo modello, si farebbe qualcosa del genere if (config.useAlgoA) impl = new AlgoA() else impl = new AlgoB()), quindi questa risposta non è corretta.
Borek Bernard,

13
Sicuro che potresti farlo, ma poi non stai usando il modello di modello. In effetti, è quasi esattamente come apparirà il codice che crea l'istanza di strategia!
thehouse

21
-1, penso che questa risposta (anche se non completamente sbagliata), manchi il punto in cui si trovano le vere differenze. La risposta di @ tvanfosson è molto migliore.
Doc Brown,

1
@Karoly Nyisztor Entrambi possono "sostituire il comportamento" e "fornire punti di estensione". Che si tratti di un comportamento o di un'estensione, dipende davvero dal contesto in cui si applica un determinato modello. Puoi anche definire una "strategia" per ogni sottoclasse del modello di metodo del modello o "estensione" per ogni classe di strategia nel modello di strategia. Il fatto è che fanno la stessa cosa TRANNE la differenza menzionata da questa risposta. Quindi questa è la risposta giusta.
Andy,

1
Un algoritmo concreto è scelto allo stesso modo per entrambi i modelli. La scelta viene fatta invocando new ConcreteAlgorithm1()contro new ConcreteAlgorithm2(). Ovviamente la scelta avviene in fase di esecuzione (fare una scelta dell'algoritmo in fase di compilazione significherebbe codificarla a fondo). La differenza principale tra i due è come viene implementato l'algoritmo concreto. È implementato come sottoclasse o come interfaccia separata? Il primo è un modello. Quest'ultima è una strategia. La differenza può essere sintetizzata come composizione vs eredità, che è un tema comune del libro GoF.
jaco0646,

138

Il modello di modello viene utilizzato quando una determinata operazione presenta alcuni comportamenti invarianti che possono essere definiti in termini di altri comportamenti primitivi variabili. La classe astratta definisce i comportamenti invarianti, mentre le classi di implementazione hanno definito i metodi dipendenti.

In una strategia, le implementazioni del comportamento sono indipendenti: ogni classe di implementazione definisce il comportamento e non esiste un codice condiviso tra di loro. Entrambi sono modelli comportamentali e, come tali, sono consumati più o meno allo stesso modo dai clienti. In genere le strategie hanno un unico metodo pubblico: il execute()metodo, mentre i modelli possono definire un insieme di metodi pubblici e un insieme di primitive private di supporto che le sottoclassi devono implementare.

I due motivi potrebbero essere facilmente usati insieme. È possibile disporre di un modello di strategia in cui diverse implementazioni appartengono a una famiglia di strategie implementate utilizzando un modello di modello.


Questo suona bene per me, tuttavia perché WikiPedia menziona che "il modello di strategia consiste nel selezionare il comportamento di un algoritmo in fase di esecuzione"? Potrebbe anche essere usato per selezionare il comportamento dell'algoritmo in fase di compilazione, proprio come il metodo template? Mi sto perdendo qualcosa?
BornToCode

2
@BornToCode Suppongo che ciò di cui stanno parlando sia scegliere una particolare strategia in fase di esecuzione. Ad esempio, ci sono diversi modi per trovare numericamente le radici di un'equazione. A seconda del dominio del problema o dei dati potresti scegliere Newton-Raphson, Euler o qualche altra strategia per risolvere l'equazione. Ognuna di queste è una strategia. L'algoritmo più grande, di cui la risoluzione dell'equazione è una parte, sceglie la strategia da utilizzare in base a una certa qualità del problema.
tvanfosson,

Sì, ma non è che il modello di strategia debba essere utilizzato SOLO per quei casi? Voglio dire se ho solo bisogno di selezionare il comportamento dell'algoritmo al momento della compilazione, dovrei ancora usare il modello di strategia, o non è stato pensato per essere usato in quel modo?
BornToCode

1
@BornToCode Direi che una strategia è più utile quando la scelta è dinamica. Il modello è fondamentalmente un modo per costruire comportamenti diversi e correlati per noti. Utilizzeresti qualche strategia (anche se non necessariamente il modello di strategia) per scegliere quale comportamento esemplare utilizzare. Ad esempio, l'ereditarietà del prodotto: creeresti un prodotto di base, aggiungendo funzionalità per prodotti diversi. La scelta del tipo di prodotto (classe) da istanziare potrebbe dipendere da quali tabelle / viste viene caricata. Il modello strategico non entra davvero in gioco lì.
tvanfosson,

2
@BornToCode non è uno o / o cosa, è sì-e. Applica il modello dove è appropriato, combina i modelli dove è utile.
tvanfosson,


24

Probabilmente intendi modello di modello. Hai ragione, servono bisogni molto simili. Direi che è meglio usare il metodo template nei casi in cui si dispone di un algoritmo "template" con passaggi definiti in cui le sottoclassi hanno la precedenza su questi passaggi per modificare alcuni dettagli. In caso di strategia, è necessario creare un'interfaccia e invece dell'ereditarietà si sta utilizzando la delega. Direi che è un modello un po 'più potente e forse migliore secondo i principi di inversione di dipendenza DIP. È più potente perché definisci chiaramente una nuova astrazione della strategia - un modo di fare qualcosa, che non si applica al metodo del modello. Quindi, se questa astrazione ha senso, usala. Tuttavia, l'utilizzo del metodo modello può fornire progetti più semplici in casi semplici, il che è anche importante. Considera quali parole si adattano meglio: hai un algoritmo modello? O è la cosa chiave qui che hai un'astrazione della strategia: un nuovo modo di fare qualcosa

Esempio di un metodo modello:

Application.main()
{
Init();
Run();
Done();
}

Qui erediti dall'applicazione e sostituisci esattamente cosa verrà fatto su init, esegui e completati.

Esempio di strategia:

array.sort (IComparer<T> comparer)

Qui, quando si scrive un comparatore, non si eredita da un array. L'array delega l'algoritmo di confronto a un comparatore.


3
Penso che sia un'ottima risposta
Calanus,

23

Differenza tra strategia e modello Metodo Modello Strategia rispetto al metodo Modello


Analogie

I modelli di metodi di strategia e modello hanno molte somiglianze tra loro. Entrambi i modelli di strategia e modello possono essere utilizzati per soddisfare il principio aperto-chiuso e rendere il modulo software facile da estendere senza modificare il suo codice. Entrambi i modelli rappresentano la separazione della funzionalità generica dall'attuazione dettagliata di tale funzionalità. Tuttavia, differiscono leggermente in termini di granularità che offrono.


differenze

Ecco alcune delle differenze che ho osservato mentre studiavo questi due schemi:

  1. In Strategia, l'accoppiamento tra client e strategia è più lento, mentre in Metodo modello i due moduli sono più strettamente accoppiati.
  2. In Strategia, viene utilizzata principalmente un'interfaccia sebbene la classe astratta possa anche essere utilizzata a seconda della situazione e la classe concreta non viene utilizzata mentre nel metodo Modello viene utilizzata principalmente la classe astratta o la classe concreta, l'interfaccia non viene utilizzata.
  3. Nel modello di strategia, generalmente l'intero comportamento della classe è rappresentato in termini di un'interfaccia, d'altra parte, il metodo Template viene utilizzato per ridurre la duplicazione del codice e il codice boilerplate viene definito nel framework di base o nella classe astratta. Nel metodo modello, può anche esserci una classe concreta con implementazione predefinita.
  4. In parole semplici, puoi cambiare l'intera strategia (algoritmo) nel modello Strategia, tuttavia, nel metodo Modello, cambiano solo alcune cose (parti dell'algoritmo) e il resto delle cose rimane invariato. Nel metodo modello, i passaggi invarianti sono implementati in una classe base astratta, mentre ai passaggi variante viene fornita un'implementazione predefinita o nessuna implementazione. Nel metodo Modello, il progettista del componente impone i passaggi richiesti di un algoritmo e l'ordine dei passaggi, ma consente al client del componente di estendere o sostituire un numero di questi passaggi.

L'immagine è tratta dal blog morso .


19

Ereditarietà contro aggregazione (is-a contro has-a). Sono due modi per raggiungere lo stesso obiettivo.

Questa domanda mostra alcuni compromessi tra le scelte: ereditarietà e aggregazione


11

Entrambi sono molto simili ed entrambi sono consumati dal codice client in modi simili. A differenza di quanto dice la risposta più popolare sopra, entrambi consentono la selezione dell'algoritmo in fase di esecuzione .

La differenza tra i due è che mentre il modello di strategia consente a diverse implementazioni di utilizzare modi completamente diversi di raggiungere il risultato desiderato, il modello di modello di modello specifica un algoritmo generale (il metodo "modello") che viene utilizzato per ottenere il risultato - - l'unica scelta lasciata alle implementazioni specifiche (sottoclassi) sono alcuni dettagli di detto metodo modello. Questo viene fatto facendo in modo che il metodo del modello faccia call (s) a uno o più metodi astratti che sono sovrascritti (cioè implementati) dalle sottoclassi, a differenza del metodo del modello che di per sé non è astratto e non sovrascritto dalle sottoclassi .

Il codice client effettua una chiamata al metodo template utilizzando un riferimento / puntatore del tipo di classe astratto che punta a un'istanza di una delle sottoclassi concrete che possono essere determinate in fase di esecuzione proprio come durante l'utilizzo del modello di strategia.


9

Metodo modello:

  1. Si basa sull'eredità
  2. Definisce lo scheletro dell'algoritmo che non può essere modificato dalle sottoclassi. Solo determinate operazioni possono essere sovrascritte in sottoclassi
  3. La classe genitore controlla completamente l'algoritmo e differisce solo alcuni passaggi da classi concrete
  4. Il binding viene eseguito al momento della compilazione

Struttura template_method :

inserisci qui la descrizione dell'immagine

Strategia:

  1. Si basa sulla delega / composizione
  2. Cambia l'intestino dell'oggetto modificando il comportamento del metodo
  3. È usato per passare da una famiglia di algoritmi a un'altra
  4. Cambia il comportamento dell'oggetto in fase di esecuzione sostituendo completamente un algoritmo con un altro algoritmo in fase di esecuzione
  5. Il binding viene eseguito in fase di esecuzione

Struttura strategica :

inserisci qui la descrizione dell'immagine

Dai un'occhiata al metodo Template e agli articoli di strategia per una migliore comprensione.

Articoli correlati:

Il modello di progettazione del modello in JDK non è riuscito a trovare un metodo che definisce un insieme di metodi da eseguire in ordine

Esempio reale del modello di strategia


3

No, non sono necessariamente consumati allo stesso modo. Il modello "metodo modello" è un modo per fornire "guida" ai futuri implementatori. Stai dicendo loro: "Tutti gli oggetti Person devono avere un numero di previdenza sociale" (questo è un esempio banale ma riesce a far passare l'idea correttamente).

Il modello di strategia consente di attivare e disattivare più possibili implementazioni. Non è (di solito) implementato tramite ereditarietà, ma invece lasciando passare il chiamante nell'implementazione desiderata. Un esempio potrebbe essere quello di consentire a un ShippingCalculator di essere fornito con una delle diverse modalità di calcolo delle imposte (un'implementazione NoSalesTax e un'implementazione PercentageBasedSalesTax).

Quindi, a volte, il client dirà effettivamente all'oggetto quale strategia usare. Come in

myShippingCalculator.CalculateTaxes(myCaliforniaSalesTaxImpl);

Ma il client non lo farebbe mai per un oggetto basato sul Metodo modello. In effetti, il client potrebbe non sapere nemmeno che un oggetto si basa sul metodo modello. Quei metodi astratti nel modello Metodo modello potrebbero persino essere protetti, nel qual caso il client non saprebbe nemmeno che esistano.


3

Ti consiglierei di leggere questo articolo. Spiega le differenze su un esempio di caso reale.

Citazione dall'articolo

" Come si può vedere, le classi di implementazione dipendono anche dalla classe del metodo del modello. Questa dipendenza provoca la modifica del metodo del modello se si vogliono cambiare alcuni dei passaggi dell'algoritmo. Dall'altro lato la strategia incapsula completamente l'algoritmo. classi per definire completamente un algoritmo. Pertanto, se arriva una modifica, è necessario modificare il codice per le classi precedentemente scritte. Questo è stato il motivo principale per cui ho scelto la strategia per la progettazione delle classi.

Una caratteristica del metodo template è che il metodo template controlla l'algoritmo. Che può essere una buona cosa in altre situazioni, ma nel mio problema questo mi stava limitando a progettare le classi. D'altra parte la strategia non controlla i passaggi di un algoritmo che mi consente di aggiungere metodi di conversione completamente diversi. Quindi nel mio caso la strategia mi aiuta a implementarla.

Uno svantaggio della strategia è che c'è troppa ridondanza del codice e meno condivisione del codice. Come è ovvio nell'esempio presentato di questo articolo, devo ripetere lo stesso codice in quattro classi ancora e ancora. Pertanto è difficile da mantenere perché se l'implementazione del nostro sistema come il passaggio 4 che è comune a tutti è cambiata, dovrò aggiornarlo in tutte e 5 le classi. Dall'altro lato, nel metodo del modello, posso solo cambiare la superclasse e le modifiche si riflettono nelle sottoclassi. Pertanto, il metodo template fornisce una ridondanza molto bassa e un'alta quantità di condivisione del codice tra le classi.

La strategia consente inoltre di modificare l'algoritmo in fase di esecuzione. Nel metodo modello si dovrà reinizializzare l'oggetto. Questa caratteristica della strategia offre una grande flessibilità. Dal punto di vista progettuale si deve preferire la composizione all'eredità. Pertanto, l'utilizzo del modello strategico è diventato anche la scelta principale per lo sviluppo.


2

Il modello di modello è simile al modello di strategia. Questi due modelli differiscono per portata e metodologia.

La strategia viene utilizzata per consentire ai chiamanti di variare un intero algoritmo, ad esempio come calcolare diversi tipi di imposta, mentre il Metodo modello viene utilizzato per variare i passaggi di un algoritmo. Per questo motivo, la strategia è più grossolana. Il modello consente controlli più precisi nel corso delle operazioni e tuttavia consente di variare le implementazioni di questi dettagli.

L'altra differenza principale è che la strategia utilizza la delega mentre il metodo modello utilizza l'ereditarietà. In Strategia, l'algoritmo è delegato a un'altra classe xxxStrategy a cui il soggetto farà riferimento, ma con Template si esegue la sottoclasse dei metodi di base e di sostituzione per apportare modifiche.

da http://cyruscrypt.blogspot.com/2005/07/template-vs-strategy-patterns.html


2

Nelle sottoclassi del modello di strategia è in esecuzione lo spettacolo e controllano l'algoritmo. Qui il codice è duplicato nelle sottoclassi. La conoscenza dell'algoritmo e come implementarlo è distribuita su molte classi.

Nel modello di modello, la classe base ha un algoritmo. Massimizza il riutilizzo tra le sottoclassi. Poiché l'algoritmo si trova in un posto, la classe base lo protegge.


2

Modello di progettazione strategica

  • Supporta la composizione.
  • Fornisce la flessibilità di modificare il comportamento dell'oggetto in fase di esecuzione.
  • Meno accoppiamento tra il codice client e il codice soluzione / algoritmo.

Modello di modello di progettazione

  • Favorisce l'eredità rispetto alla composizione
  • Definisci l'algoritmo nella tua classe base. I singoli pezzi di algoritmo possono essere personalizzati in classi secondarie.

1

Modello modello:

Il metodo modello consiste nel consentire alle sottoclassi di ridefinire determinati passaggi dell'algoritmo, senza modificare la struttura principale e i passaggi dell'algoritmo, definiti nella classe base. Il modello di modello di solito utilizza l'ereditarietà, quindi è possibile fornire un'implementazione generica di algoritmi nella classe base, che la sottoclasse potrebbe scegliere di sovrascrivere se necessario.

public abstract class RobotTemplate {
    /* This method can be overridden by a subclass if required */
    public void start() {
        System.out.println("Starting....");
    }

    /* This method can be overridden by a subclass if required */
    public void getParts() {
        System.out.println("Getting parts....");
    }

    /* This method can be overridden by a subclass if required */
    public void assemble() {
        System.out.println("Assembling....");
    }

    /* This method can be overridden by a subclass if required */
    public void test() {
        System.out.println("Testing....");
    }

    /* This method can be overridden by a subclass if required */
    public void stop() {
        System.out.println("Stopping....");
    }

    /*
     * Template algorithm method made up of multiple steps, whose structure and
     * order of steps will not be changed by subclasses.
     */
    public final void go() {
        start();
        getParts();
        assemble();
        test();
        stop();
    }
}


/* Concrete subclass overrides template step methods as required for its use */
public class CookieRobot extends RobotTemplate {
    private String name;

    public CookieRobot(String n) {
        name = n;
    }

    @Override
    public void getParts() {
        System.out.println("Getting a flour and sugar....");
    }

    @Override
    public void assemble() {
        System.out.println("Baking a cookie....");
    }

    @Override
    public void test() {
        System.out.println("Crunching a cookie....");
    }

    public String getName() {
        return name;
    }
}

Nota nel codice sopra, i passaggi dell'algoritmo go () saranno sempre gli stessi, ma le sottoclassi potrebbero definire una ricetta diversa per eseguire un determinato passaggio.

Modello di strategia:

Il modello di strategia consiste nel consentire al client di selezionare l'implementazione di algoritmi concreti in fase di esecuzione. Tutti gli algoritmi sono isolati e indipendenti, ma implementano un'interfaccia comune e non esiste la nozione di definire particolari passaggi all'interno dell'algoritmo.

/**
 * This Strategy interface is implemented by all concrete objects representing an
 * algorithm(strategy), which lets us define a family of algorithms.
 */
public interface Logging {
    void write(String message);
}

/**
 * Concrete strategy class representing a particular algorithm.
 */
public class ConsoleLogging implements Logging {

    @Override
    public void write(String message) {
        System.out.println(message); 
    }

}

/**
 * Concrete strategy class representing a particular algorithm.
 */
public class FileLogging implements Logging {

    private final File toWrite;

    public FileLogging(final File toWrite) {
        this.toWrite = toWrite;
    }

    @Override
    public void write(String message) {
        try {
            final FileWriter fos = new FileWriter(toWrite);
            fos.write(message);
            fos.close();
        } catch (IOException e) {
            System.out.println(e);
        }
    }

}

Per il codice sorgente completo, controlla il mio repository github .


0

La strategia è esposta come un metodo di interfaccia e modello come la classe astratta. Questo è generalmente usato molto nei framework. ad esempio, la classe MessageSource di Spring Framework è un'interfaccia strategica per la risoluzione dei messaggi. Il client utilizza un'implementazione particolare (strategia) di questa interfaccia.

E l'implementazione astratta della stessa interfaccia AbstractMessageSource, che ha un'implementazione comune di risoluzione dei messaggi ed espone il metodo abstract di risolCode () in modo che le sottoclassi possano implementarli a modo loro. AbstractMessageSource è un esempio di metodo modello.

http://docs.spring.io/spring/docs/4.1.7.RELEASE/javadoc-api/org/springframework/context/support/AbstractMessageSource.html


0

Nel metodo modello di questo modello di progettazione, una o più fasi dell'algoritmo possono essere ignorate da sottoclassi per consentire comportamenti diversi garantendo al contempo che l'algoritmo generale sia ancora seguito (Wiki).

Il nome del modello Metodo modello indica di cosa si tratta. Supponiamo di avere un metodo CalculateSomething () e di voler modellare questo metodo. Questo metodo verrà dichiarato nella classe base un metodo non virtuale. Supponiamo che il metodo assomigli a questo.

CalculateSomething(){
    int i = 0;
    i = Step1(i);
    i++;
    if (i> 10) i = 5;
    i = Step2(i);
    return i;

} L'implementazione del metodo Step1 e Step2 può essere fornita da classi derivate.

Nel modello di strategia non esiste un'implementazione fornita dalla base (questo è il motivo per cui la base è davvero un'interfaccia nel diagramma di classe)

L'esempio classico è l'ordinamento. In base al numero di oggetti deve essere ordinato, viene creata la classe di algoritmo appropriata (unione, bolla, rapida, ecc.) E l'intero algoritmo viene incapsulato in ciascuna classe.

Ora possiamo implementare l'ordinamento come metodo modello? Certamente puoi, ma non troverai molto / qualsiasi comunanza da sottrarre e collocare nell'implementazione di base. Quindi vanifica lo scopo del modello di metodo del modello.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.