Qual é a diferença entre o método de modelo e os padrões de estratégia?


161

Alguém pode me explicar qual é a diferença entre o padrão do método do modelo e o padrão da estratégia?

Até onde eu sei, eles são 99% iguais - a única diferença é que o padrão do método do modelo tem uma classe abstrata como a classe base, enquanto a classe de estratégia usa uma interface implementada por cada classe de estratégia concreta.

No entanto, no que diz respeito ao cliente, eles são consumidos exatamente da mesma maneira - isso está correto?


2
Este post no SO tem uma resposta melhor para a mesma pergunta: stackoverflow.com/questions/464524/...
Gob00st

12
A questão à qual o gob00st está associado é a diferença entre estratégia e ponte. Não é a resposta para esta pergunta.
bluekeys 30/01

Respostas:


135

A principal diferença entre os dois é quando o algoritmo concreto é escolhido.

Com o padrão Template Method isso acontece em tempo de compilação por subclassificação o modelo. Cada subclasse fornece um algoritmo concreto diferente, implementando os métodos abstratos do modelo. Quando um cliente chama métodos da interface externa do modelo, o modelo chama seus métodos abstratos (sua interface interna) conforme necessário para chamar o algoritmo.

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

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

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

Por outro lado, o padrão Estratégia permite que um algoritmo seja escolhido em tempo de execução por contenção . Os algoritmos concretos são implementados por classes ou funções separadas, que são passadas para a estratégia como um parâmetro para seu construtor ou para um método setter. O algoritmo escolhido para este parâmetro pode variar dinamicamente com base no estado ou nas entradas do programa.

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

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

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

Em suma:

  • Padrão do método de modelo: tempo de compilação seleção de algoritmo em por subclassificação
  • Padrão de estratégia: seleção do algoritmo em tempo de execução por contenção

47
Ambos os padrões oferecem suporte à seleção em tempo de execução do algoritmo usado (para o Método do modelo, você faria algo assim if (config.useAlgoA) impl = new AlgoA() else impl = new AlgoB()), portanto esta resposta está incorreta.
Borek Bernard

13
Claro que você poderia fazer isso, mas não estará usando o Modelo Padrão. De fato, é quase exatamente como será o código que cria a instância Strategy!
thehouse

21
-1, acho que essa resposta (embora não esteja completamente errada) perde o ponto em que estão as diferenças reais. A resposta do @ tvanfosson é muito melhor.
Doc Brown

1
@Karoly Nyisztor Ambos podem "substituir o comportamento" e "fornecer pontos de extensão". Se algo é um comportamento ou uma extensão, é realmente até o contexto de onde você aplica um determinado padrão. Você também pode chamar cada subclasse do padrão de método do modelo de "estratégia" ou chamar cada classe de estratégia no padrão de estratégia de "extensão", é apenas uma redação. O fato é que eles fazem a mesma coisa, EXCETO a diferença mencionada nesta resposta. Então esta é a resposta certa.
Andy

1
Um algoritmo concreto é escolhido da mesma maneira para os dois padrões. A escolha é feita invocando new ConcreteAlgorithm1()versus new ConcreteAlgorithm2(). Obviamente, a escolha acontece no tempo de execução (fazer uma escolha de algoritmo no tempo de compilação significaria codificá-la). A principal diferença entre os dois é como o algoritmo concreto é implementado. É implementado como uma subclasse ou como uma interface separada? O primeiro é um modelo. O último é uma estratégia. A diferença pode ser resumida como composição versus herança, que é um tema comum do livro do GoF.
jaco0646 15/04

138

O padrão de modelo é usado quando uma operação específica possui comportamento (s) invariável (s) que pode ser definido em termos de outros comportamentos primitivos variáveis. A classe abstrata define o comportamento invariável, enquanto as classes de implementação definem os métodos dependentes.

Em uma estratégia, as implementações de comportamento são independentes - cada classe de implementação define o comportamento e não há código compartilhado entre elas. Ambos são padrões comportamentais e, como tal, são consumidos da mesma maneira pelos clientes. Normalmente, as estratégias têm um único método público - o execute()método, enquanto os modelos podem definir um conjunto de métodos públicos e um conjunto de primitivas privadas de suporte que as subclasses devem implementar.

Os dois padrões podem ser facilmente usados ​​juntos. Você pode ter um padrão de estratégia em que várias implementações pertencem a uma família de estratégias implementadas usando um padrão de modelo.


Isso me parece correto, no entanto, por que o WikiPedia menciona que "o padrão de estratégia é para que o comportamento de um algoritmo seja selecionado em tempo de execução"? Também poderia ser usado para selecionar o comportamento do algoritmo em tempo de compilação, assim como o método de modelo? Estou esquecendo de algo?
BornToCode 31/07

2
@BornToCode Eu diria que eles estão falando sobre escolher uma estratégia específica em tempo de execução. Por exemplo, existem várias maneiras de encontrar numericamente as raízes de uma equação. Dependendo do domínio do problema ou dos dados, você pode escolher Newton-Raphson, Euler ou alguma outra estratégia para resolver a equação. Cada um deles é uma estratégia. O algoritmo maior, do qual resolver a equação é uma parte, escolhe a estratégia a ser empregada com base em alguma qualidade do problema.
tvanfosson

Sim, mas não é como o padrão de estratégia deve ser usado SOMENTE nesses casos? Quero dizer, se eu só precisar selecionar o comportamento do algoritmo em tempo de compilação, ainda devo usar o padrão de estratégia, ou não foi para ser usado dessa maneira?
BornToCode 31/07

1
@BornToCode Eu diria que uma estratégia é mais útil quando a escolha é dinâmica. O modelo é basicamente uma maneira de criar comportamentos diferentes e relacionados para os conhecidos. Você usaria alguma estratégia (embora não necessariamente o padrão de estratégia) para escolher qual modelo de comportamento empregar. Por exemplo, herança de produto - você criaria um produto base e adicionaria recursos para diferentes produtos. A escolha de qual tipo de produto (classe) instanciar pode depender de quais tabelas / visualizações é carregada. O padrão de estratégia realmente não entra em jogo lá.
tvanfosson

2
@BornToCode não é uma coisa ou / ou coisa, é sim-e. Aplique o padrão onde for apropriado, combine padrões onde for útil.
31415 javascript:

26

Eu acho que os diagramas de classes de ambos os padrões estão mostrando as diferenças.

Estratégia
Encapsula um algoritmo dentro de uma classe
Link para a imagem insira a descrição da imagem aqui

Método de modelo
Adie as etapas exatas de um algoritmo para uma subclasse
Link to Image insira a descrição da imagem aqui


24

Você provavelmente quer dizer padrão de método de modelo. Você está certo, eles servem necessidades muito semelhantes. Eu diria que é melhor usar o método de modelo nos casos em que você tem um algoritmo de "modelo" tendo etapas definidas nas quais as subclasses substituem essas etapas para alterar alguns detalhes. No caso de estratégia, você precisa criar uma interface e, em vez de herança, você está usando delegação. Eu diria que é um padrão um pouco mais poderoso e talvez melhor de acordo com os princípios de inversão de dependência DIP. É mais poderoso porque você define claramente uma nova abstração da estratégia - uma maneira de fazer algo, que não se aplica ao método de modelo. Portanto, se essa abstração faz sentido - use-a. No entanto, o uso do método de modelo pode fornecer designs mais simples em casos simples, o que também é importante. Considere quais palavras se encaixam melhor: você tem um algoritmo de template? Ou é a coisa principal aqui que você tem uma abstração da estratégia - nova maneira de fazer algo

Exemplo de um método de modelo:

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

Aqui você herda da aplicação e substitui o que exatamente será feito no init, run e done.

Exemplo de estratégia:

array.sort (IComparer<T> comparer)

Aqui, ao escrever um comparador, você não herda de uma matriz. Matriz delega o algoritmo de comparação para um comparador.


3
Penso que esta é uma grande resposta
Calanus

23

Diferença entre Estratégia e Modelo Padrão Estratégia versus Modelo Método


Semelhanças

Os padrões de estratégia e modelo têm muitas semelhanças entre eles. Os padrões dos métodos Strategy e Template podem ser usados ​​para satisfazer o Princípio Aberto-Fechado e facilitar a extensão do módulo de software sem alterar seu código. Ambos os padrões representam a separação da funcionalidade genérica da implementação detalhada dessa funcionalidade. No entanto, eles diferem um pouco em termos de granularidade que oferecem.


Diferenças

Aqui estão algumas das diferenças que observei ao estudar esses dois padrões:

  1. Na estratégia, o acoplamento entre o cliente e a estratégia é mais flexível, enquanto no método de modelo, os dois módulos são mais fortemente acoplados.
  2. Em Estratégia, geralmente é usada uma interface, embora a classe abstrata também possa ser usada dependendo da situação, e a classe concreta não é usada, enquanto no método Template é usada principalmente a classe abstrata ou classe concreta, a interface não é usada.
  3. No padrão Estratégia, geralmente o comportamento inteiro da classe é representado em termos de uma interface; por outro lado, o método Template é usado para reduzir a duplicação de código e o código padrão é definido na estrutura base ou na classe abstrata. No método de modelo, pode até haver uma classe concreta com implementação padrão.
  4. Em palavras simples, você pode alterar toda a estratégia (algoritmo) no padrão Strategy, no entanto, no método Template, apenas algumas coisas mudam (partes do algoritmo) e o restante permanece inalterado. No método de modelo, as etapas invariantes são implementadas em uma classe base abstrata, enquanto as etapas variantes recebem uma implementação padrão ou nenhuma implementação. No método Template, o designer do componente exige as etapas necessárias de um algoritmo e a ordem das etapas, mas permite que o cliente do componente estenda ou substitua algum número dessas etapas.

A imagem é retirada do blog de tamanho reduzido .


19

Herança versus agregação (is-a versus has-a). São duas maneiras de alcançar o mesmo objetivo.

Esta pergunta mostra alguns dos trade-offs entre as opções: Herança vs. Agregação


11

Ambos são muito parecidos e são consumidos pelo código do cliente de maneiras semelhantes. Diferentemente do que diz a resposta mais popular acima, ambos permitem a seleção de algoritmos em tempo de execução .

A diferença entre os dois é que, embora o padrão de estratégia permita que diferentes implementações usem maneiras completamente diferentes de alcançar o resultado desejado, o padrão do método de modelo especifica um algoritmo abrangente (o método "modelo") que é usado para obter o resultado - - a única opção que resta para as implementações específicas (subclasses) são certos detalhes do referido método de modelo. Isso é feito com o método template fazer chamadas para um ou mais métodos abstratos que são substituídos (ou seja, implementados) pelas subclasses, ao contrário do método template que não é abstrato e não é substituído pelas subclasses .

O código do cliente faz uma chamada para o método de modelo usando uma referência / ponteiro do tipo de classe abstrata apontando para uma instância de uma das subclasses concretas que podem ser determinadas em tempo de execução, assim como durante o uso do Padrão de Estratégia.


9

Método de modelo:

  1. É baseado em herança
  2. Define o esqueleto do algoritmo que não pode ser alterado por subclasses. Somente determinadas operações podem ser substituídas nas subclasses
  3. A classe pai controla completamente o algoritmo e difere apenas certas etapas das classes concretas
  4. A ligação é feita em tempo de compilação

Estrutura do Template_method :

insira a descrição da imagem aqui

Estratégia:

  1. É baseado em delegação / composição
  2. Muda as tripas do objeto , modificando o comportamento do método
  3. É usado para alternar entre a família de algoritmos
  4. Ele altera o comportamento do objeto no tempo de execução, substituindo completamente um algoritmo por outro algoritmo no tempo de execução
  5. A ligação é feita em tempo de execução

Estrutura da estratégia :

insira a descrição da imagem aqui

Dê uma olhada no método de modelo e nos artigos de estratégia para melhor compreensão.

Mensagens relacionadas:

O padrão de design do modelo no JDK não pôde encontrar um método que define o conjunto de métodos a serem executados em ordem

Exemplo do mundo real do padrão de estratégia


3

Não, eles não são necessariamente consumidos da mesma maneira. O padrão "método de modelo" é uma maneira de fornecer "orientação" aos futuros implementadores. Você está dizendo a eles: "Todos os objetos de Pessoa devem ter um Número de Seguro Social" (esse é um exemplo trivial, mas transmite a idéia corretamente).

O padrão de estratégia permite que várias implementações possíveis sejam ativadas e desativadas. Ele não é (geralmente) implementado por herança, mas por permitir que o chamador passe na implementação desejada. Um exemplo pode estar permitindo que um ShippingCalculator seja fornecido com uma das várias maneiras diferentes de calcular impostos (uma implementação NoSalesTax e talvez uma implementação PercentageBasedSalesTax).

Então, às vezes, o cliente realmente diz ao objeto qual estratégia usar. Como em

myShippingCalculator.CalculateTaxes(myCaliforniaSalesTaxImpl);

Mas o cliente nunca faria isso para um objeto baseado no método de modelo. De fato, o cliente pode nem saber que um objeto é baseado no Método do Modelo. Esses métodos abstratos no padrão Método do modelo podem até ser protegidos; nesse caso, o cliente nem saberia que eles existem.


3

Eu sugiro que você leia este artigo. Explica as diferenças em um exemplo de caso real.

Citação do artigo

" Como se pode ver, as classes de implementação também dependem da classe de método do modelo. Essa dependência faz com que o método seja alterado, se alguém quiser alterar algumas das etapas do algoritmo. Por outro lado, a estratégia encapsula completamente o algoritmo. Ela fornece a implementação classes para definir completamente um algoritmo.Portanto, se houver alguma mudança, é necessário alterar o código das classes escritas anteriormente.Esta foi a principal razão pela qual escolhi a estratégia para projetar as classes.

Uma característica do método de modelo é que ele controla o algoritmo. O que pode ser uma coisa boa em outra situação, mas no meu problema, isso estava me restringindo a projetar as classes. Por outro lado, a estratégia não controla as etapas de um algoritmo que me permite adicionar métodos de conversão completamente diferentes. Portanto, no meu caso, a estratégia me ajuda na implementação.

Uma desvantagem da estratégia é que há muita redundância de código e menos compartilhamento de código. Como é óbvio no exemplo apresentado deste artigo, tenho que repetir o mesmo código em quatro classes várias vezes. Portanto, é difícil de manter, porque se a implementação de nosso sistema, como a etapa 4, que é comum a todos, for alterada, terei que atualizar isso nas 5 classes. Por outro lado, no método de modelo, só posso alterar a superclasse e as alterações são refletidas nas subclasses. Portanto, o método de modelo fornece uma quantidade muito baixa de redundância e alta quantidade de compartilhamento de código entre as classes.

A estratégia também permite alterar o algoritmo em tempo de execução. No método de modelo, será necessário reinicializar o objeto. Esse recurso da estratégia oferece grande flexibilidade. Do ponto de vista do design, é preciso preferir a composição do que a herança. Portanto, o uso do padrão de estratégia também se tornou a principal escolha para o desenvolvimento ".


2

O padrão do modelo é semelhante ao padrão da estratégia. Esses dois padrões diferem em escopo e metodologia.

A estratégia é usada para permitir que os chamadores variem um algoritmo inteiro, como calcular diferentes tipos de impostos, enquanto o Método do Modelo é usado para variar as etapas de um algoritmo. Por esse motivo, a estratégia é mais grosseira. O Modelo permite controles mais refinados na sequência de operações e ainda permite que as implementações desses detalhes variem.

A outra principal diferença é que a Strategy usa delegação enquanto o Method Template usa herança. Em Strategy, o algoritmo é delegado para outra classe xxxStrategy à qual o assunto fará referência, mas com Template você subclassifica a base e substitui os métodos para fazer alterações.

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


2

No padrão de estratégia, as subclasses estão executando o programa e controlam o algoritmo. Aqui o código é duplicado nas subclasses. O conhecimento do algoritmo e como implementá-lo é distribuído por várias classes.

No padrão de modelo, a classe base possui algoritmo. Maximiza a reutilização entre as subclasses. Como o algoritmo está em um só lugar, a classe base o protege.


2

Padrão de Design de Estratégia

  • Suporta composição.
  • Fornece a flexibilidade de alterar o comportamento do objeto em tempo de execução.
  • Menos acoplamento entre o código do cliente e o código da solução / algoritmo.

Modelo Método Design Pattern

  • Favorece a herança sobre a composição
  • Defina o algoritmo na sua classe base. Partes individuais do algoritmo podem ser personalizadas em classes filho.

1

Padrão do modelo:

O método Template é permitir que as subclasses redefinam certas etapas do algoritmo, sem alterar a estrutura principal e as etapas do algoritmo, definidas na classe base. O padrão de modelo geralmente usa herança, portanto, uma implementação genérica de algoritmos pode ser fornecida na classe base, que a subclasse pode optar por substituir, se necessário.

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;
    }
}

Observe no código acima, as etapas do algoritmo go () sempre serão as mesmas, mas as subclasses podem definir uma receita diferente para executar uma etapa específica.

Padrão de Estratégia:

O padrão de estratégia é permitir que o cliente selecione a implementação de algoritmos concretos em tempo de execução. Todos os algoritmos são isolados e independentes, mas implementam uma interface comum e não há noção de definição de etapas específicas dentro do 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);
        }
    }

}

Para obter o código fonte completo, consulte meu repositório do github .


0

A estratégia é exposta como um método de interface e modelo como a classe abstrata. Isso geralmente é muito usado em estruturas. por exemplo, a classe MessageSource do Spring framework é uma interface de estratégia para resolver mensagens. O cliente usa uma implementação específica (estratégia) dessa interface.

E a implementação abstrata da mesma interface AbstractMessageSource, que possui implementação comum de resolução de mensagens e expõe o método abstrato resolveCode () para que as subclasses possam implementá-las de sua maneira. AbstractMessageSource é um exemplo de método de modelo.

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


0

No método de modelo desse padrão de design, uma ou mais etapas do algoritmo podem ser substituídas por subclasses para permitir comportamentos diferentes, garantindo que o algoritmo abrangente ainda seja seguido (Wiki).

O método Template do nome do padrão significa o que é. Digamos que temos um método CalculateSomething () e queremos modelar esse método. Este método será declarado na classe base como um método não virtual. Digamos que o método fique assim.

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

} A implementação dos métodos Step1 e Step2 pode ser fornecida por classes derivadas.

No Padrão de Estratégia, não há implementação fornecida pela base (Esta é a razão pela qual a base é realmente uma interface no diagrama de classes)

O exemplo clássico é de classificação. Com base no número de objetos que precisam ser classificados, a classe de algoritmo apropriada (mesclagem, bolha, rápida etc.) é criada e o algoritmo inteiro é encapsulado em cada classe.

Agora podemos implementar a classificação como um método de modelo? Certamente você pode, mas você não encontrará muita / nenhuma semelhança a ser abstraída e colocada na implementação básica. Portanto, isso derrota o objetivo do padrão de método do modelo.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.