Pergunta

Alguém pode me informar algumas situações de exemplo em que o método do modelo - o padrão deve ser usado?

Dê-me algum uso do mundo real de sua própria experiência.

(Até agora, achei útil apenas para mapear dados na camada DA. Desculpe !!!)

Foi útil?

Solução

Tentei dar a você alguns exemplos do mundo real e algumas situações comuns em que o padrão de método de modelo deve ser usado.

  • Quando você deseja que seu programa seja "aberto para extensão" e também "fechado para modificação". Isso significa que o comportamento do módulo pode ser estendido, de modo que possamos fazer com que o módulo se comporte de maneiras novas e diferentes como os requisitos da mudança de aplicativo ou para atender às necessidades de novos aplicativos. No entanto, o código fonte desse módulo é inviolável. Ninguém pode fazer alterações no código -fonte. No exemplo a seguir, você pode adicionar uma nova maneira de cálculo salarial (como classe remotamente) sem alterar os códigos anteriores.

    public abstract class Salary {
    
       public final void calculate() {
            System.out.println("First shared tasks is done.");
            getBaseSalary();
            System.out.println("Second shared tasks is done.");
       }
    
       public abstract void getBaseSalary();
    
    }
    
    public class Hourly extends Salary {
    
        @Override
        public void getBaseSalary() {
            System.out.println("Special Task is done.");
        }
    
    }
    
    public class Test {
    
        public static void main(String[] args) {
            Salary salary = ....
            salary.calculate();
        }
    }
    
  • Quando você enfrenta muitas linhas de códigos que são duplicadas ao adiar apenas algumas etapas do seu algoritmo. Quando você está implementando o conteúdo de um método ou função, pode encontrar alguma seção do seu código que varie de um tipo para outro. O recurso dessas seções é que se pode redefinir ou modificar essas seções de um método ou função sem alterar a estrutura principal do algoritmo (método ou função). Por exemplo, se você deseja resolver esse problema sem esse padrão, enfrentará esta amostra:

function0: function1: ... functionn:

1       1               1
2       2               2
...     ...             ...
5       6               n
3       3               3
4       4               4
...     ...             ...

Como você pode ver, os CODS da seção 5, 6, n são diferentes de uma função para outra, no entanto, você compartilhou seções como 1,2,3,4 duplicadas. Vamos considerar uma solução com uma das famosas bibliotecas Java.

public abstract class InputStream implements Closeable {

    public abstract int read() throws IOException;

    public int read(byte b[], int off, int len) throws IOException {
        ....

        int c = read();
        ....
    }

    ....

}

public class ByteArrayInputStream extends InputStream {  

    ...

    public synchronized int read() {
        return (pos < count) ? (buf[pos++] & 0xff) : -1;
        }
    ...
}
  • Quando você, como designer de uma estrutura, deseja que seus clientes apenas usem qualquer código executável que seja aprovado como um argumento para sua estrutura, que deve ligar de volta (executar) esse argumento em um determinado momento. Essa execução pode ser imediata como em um retorno de chamada síncrona, ou pode acontecer posteriormente como em um retorno de chamada assíncrona. Vamos considerar um dos famosos.

    public abstract class HttpServlet extends GenericServlet 
        implements java.io.Serializable  {
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
            ...
        }
    
    protected void service(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException {
            ....
            doGet(req, resp);
            ...
        }
        ...
    }
    }
    
    public class MyServlet extends HttpServlet {
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
    
                //do something
            ...
        }
        ...
    }
    

Outras dicas

UMA Modelo Método Padrão Fornece um esqueleto para executar qualquer tipo de algoritmo ou uma operação e permite que as subclasses redefinam a parte da lógica.

Prós: ajuste natural para estruturas de construção, para que as classes da estrutura dos pais possam transformar retornos de chamada em métodos implementados na criança.

Exemplos:

  • java.util.abstractList
  • Métodos Doget e DoPost do servlet
  • Método OnMessage da MDB
  • Classe de ação de suporte
  • Aulas de acesso a dados da primavera

Contras: restringe você a uma única herança em Java.

Uma aplicação do Método do modelo O padrão tem duas características principais:

  1. Há uma classe base (em java, apenas um com protected construtores e opcionalmente declarados como abstract) que serão subclassificados no código do cliente.
  2. dois grupos de métodos definido na classe base: a) um ou mais Métodos de modelo (normalmente apenas um) e um ou mais operação primitiva Métodos (normalmente mais de um). Cada método de modelo representa uma operação de alto nível, implementada na própria classe base em termos de operações primitivas, que devem ser implementadas/substituídas em cada subclasse específica. Normalmente, o método de modelo é público e não sobrepivável (final, em java); Sua documentação da API deve especificar com precisão quais métodos de operação primitiva ele chama e quando (ou seja, deve descrever o "algoritmo"). Um método de operação primitivo, que representa uma etapa no algoritmo, deve ser não pública, mas substituível (protected, em java), e pode ser de dois tipos: a) um método abstrato que devo ser implementado na subclasse; b) um método com uma implementação padrão/vazia que poderia ser superestimado na subclasse.

Um bom exemplo no Java 6 sdk é o execute() Método do javax.swing.SwingWorker classe (é um public final void método). Nesse caso, os métodos de operação primitiva são doInBackground(), process(List), e done(). O primeiro é abstrato e, portanto, requer uma implementação na subclasse; É chamado pelo método do modelo em um encadeamento de segundo plano. Os outros dois têm implementações vazias e, opcionalmente, podem ser substituídas na subclasse; Eles são chamados durante e no final do processamento, respectivamente, no EDT (o thread de despacho de eventos de swing), para permitir atualizações na interface do usuário.

Na minha própria experiência, às vezes usei esse padrão. Um desses casos foi uma classe base Java implementando o java.util.Iterator interface, onde next() Era o método do modelo e havia apenas um método de operação primitivo responsável por instantar uma classe de entidade de domínio específica (isso deveria ser usado quando se itera sobre uma lista de objetos persistentes da entidade de domínio, usando JDBC). Um exemplo melhor nesse mesmo aplicativo foi uma classe base em que o método do modelo implementou um algoritmo em várias etapas destinado a preencher uma "tela de manutenção de entidades comerciais" (usando o swing) de uma determinada lista de entidades persistentes; Os métodos de operações primitivos foram chamados para 1) limpar o estado atual da tela e 2) adicionar uma entidade em uma exibição de tabela dentro da tela; Opcionalmente, outras operações primitivas foram chamadas do método do modelo se a tela fosse editável.

No final, devo dizer que, embora isso certamente seja um padrão de design útil, não é tão frequentemente uma situação onde realmente é aplicável. Simplesmente ter uma classe base com métodos que são superestimados em uma subclasse (uma situação muito mais comum, na minha experiência) não é suficiente, por si só, para se qualificar como uma aplicação do padrão.

A coisa mais importante no método de modelo é que você deve definir uma série de métodos abstratos como etapas ou um algoritmo e deixar a sub -classe substituir a implementação concreta para esses métodos.

Eu me inscrevi em um dos programas de geração de documentos.

public abstract DocumentGenerator() 
{
   generateHeader();
   generateBody();
   generateDetails();
}
public HTMLDocGenerator : DocumentGenerator()
{
   public override generateBody()
   {
     //generate as in html format
   }
}

Você pode ter uma implementação diferente, como o gerador de CSV do gerador PDF e o valor aqui é que eles se comparam ao algoritmo (gerar -> cabeçalho, corpo, detalhes).

Um padrão de modelo deve ser usado quando houver um algoritmo com muitas implementações. O algoritmo é definido em uma função na classe base e a implementação é feita pela classe base e subclasses. Uma explicação detalhada com um exemplo em tempo real é apresentado em http://preciselyconcise.com/design_patterns/templatemethod.php

Vou esboçar um exemplo do mundo real em que utilizei alguns métodos de modelo.

Em um aplicativo de algoritmo de visão computacional C ++, o comportamento do algoritmo foi projetado para assumir alguns sabores de comportamento do algoritmo com base em algumas opções lidas no tempo de execução, de acordo com uma enumeração escondida em um arquivo de configuração carregado na inicialização. O esqueleto geral do algoritmo era idêntico, exceto por alguns retornos de chamada importantes recheados no meio do que seria uma seção idêntica de código que seria brutalmente duplicada apenas para chamar diferentes funções nesse nível. Esses retornos de chamada que eu queria usar foram abstraídos na classe base do método do modelo e o padrão de método de modelo impedia toda essa duplicação de código. A enumeração que usamos basicamente ditava qual subclasse eu instanciei meu ponteiro de classe base para apontar e, assim, emprestar o algoritmo seu pouco de sabor associado no comportamento.

Agora, algumas das motivações por trás dessa variedade de sabores do algoritmo em execução eram uma funcionalidade online versus offline do software que controlava nosso instrumento. O sabor off -line puxou com ele mais rico saída de depuração/diagnóstico e manteve um sistema de coordenadas local em alguns pixels de imagem, enquanto o sabor on -line mantinha as coisas em um espaço de coordenadas absolutas e mantinha preocupações específicas do instrumento em execução com toda a sua robótica e o que não. Outra enumeração impulsionou uma seleção entre um conjunto de classificadores que usamos para algum aprendizado de máquina, pois diferentes classificadores foram treinados sob diferentes conjuntos de dados que de outra forma fluíam de forma idêntica através do corpo do código, mas precisavam ser interpretados de maneira diferente, com base em algumas condições de governo para a maneira como esses dados foram criados.

Eu acredito que esse tipo de caso de uso que eu havia surgido do que foi chamado de buraco no meio problema.

Eu usei o método de modelo para a lógica de negócios, onde vários componentes compartilhavam o mesmo processo, mas a implementação foi um pouco diferente.

O método do modelo define a estrutura do esqueleto de um algoritmo, mas adia certas etapas e detalhes para as subclasses. A estrutura e o fluxo do algoritmo permanecem estáticos, mas os detalhes das etapas são adiados para subclasses.

Usei o padrão de método de modelo para preparar o conteúdo do documento. Havia muitos tipos diferentes de documentos que cada tipo tem suas próprias pequenas modificações. No entanto, o principal processo de preparação de documentos era o mesmo para todos.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top