Padrões de Design_Padrões Comportamentais - "Padrões de Estratégia"

Padrões de Design_Padrões Comportamentais - "Padrões de Estratégia"

As notas são organizadas a partir da explicação detalhada dos padrões de design Java por programadores azarões, 23 padrões de design Java (diagrama + análise do código-fonte da estrutura + combate real)

visão geral

Observe primeiro a figura abaixo: há muitos meios de transporte para escolhermos, como andar de bicicleta, de carro, de trem ou de avião.

Como programador, você precisa escolher uma ferramenta de desenvolvimento para desenvolvimento. Claro, existem muitas ferramentas para desenvolvimento de código. Você pode escolher uma ideia para desenvolvimento, também pode usar o Eclipse para desenvolvimento e também pode usar algumas outras ferramentas de desenvolvimento.

definição

  • Este modo define uma série de algoritmos e encapsula cada algoritmo para que possam ser substituídos entre si, e a alteração do algoritmo não afetará os clientes que usam o algoritmo. O padrão de estratégia pertence ao padrão de comportamento do objeto, encapsula o algoritmo, separa a responsabilidade de usar o algoritmo da implementação do algoritmo e delega a diferentes objetos o gerenciamento desses algoritmos.

estrutura

As principais funções do Padrão de Estratégia são as seguintes:

  • Classe Abstract Strategy (Strategy): Esta é uma função abstrata, geralmente implementada por uma interface ou classe abstrata. Esta função fornece todas as interfaces exigidas pelas classes de estratégia concreta.
  • Classe Concrete Strategy (Estratégia Concreta): implementa a interface definida pela estratégia abstrata e fornece implementação ou comportamento de algoritmo específico.
  • Classe de ambiente (contexto): Contém uma referência a uma classe de estratégia, que eventualmente é chamada pelo cliente.

Realização de caso

【Exemplo】Promoção

Uma loja de departamentos está realizando uma promoção anual de vendas. Lançar diferentes atividades promocionais para diferentes festivais (Festival da Primavera, Festival do Meio Outono, Natal), e os promotores mostrarão as atividades promocionais aos clientes. O diagrama de classes é o seguinte:

código mostra como abaixo:

  • Definir uma interface comum para todas as promoções em uma loja de departamentos

    // 抽象策略类
    public interface Strategy {
          
          
        void show();
    }
    
  • Definir papéis estratégicos específicos (Estratégia Concreta): ações promocionais específicas para cada festival

    // 具体策略类-为春节准备的促销活动A
    public class StrategyA implements Strategy {
          
          
    
        public void show() {
          
          
            System.out.println("买一送一");
        }
    }
    
    // 具体策略类-为中秋节准备的促销活动B
    public class StrategyB implements Strategy {
          
          
    
        public void show() {
          
          
            System.out.println("满200元减50元");
        }
    }
    
    // 具体策略类-为圣诞节准备的促销活动C
    public class StrategyC implements Strategy {
          
          
    
        public void show() {
          
          
            System.out.println("满1000元加一元换购任意200元以下商品");
        }
    }
    
  • Definir o papel do ambiente (Contexto): usado para conectar o contexto, ou seja, vender ações promocionais para os clientes, aqui pode ser entendido como um vendedor

    // 环境类-销售员
    public class SalesMan {
          
          
        
        // 聚合策略类 持有抽象策略角色的引用                              
        private Strategy strategy;                 
                                                   
        public SalesMan(Strategy strategy) {
          
                 
            this.strategy = strategy;              
        }                                          
                          
        // 向客户展示促销活动                                
        public void salesManShow(){
          
                          
            strategy.show();                       
        }                                          
    }                                              
    
  • aula de teste

    public class Client {
          
          
        public static void main(String[] args) {
          
          
            // 春节来了,使用春节促销活动
            SalesMan salesMan = new SalesMan(new StrategyA());
            // 展示促销活动
            salesMan.salesManShow();
    
            System.out.println("==============");
            // 中秋节到了,使用中秋节的促销活动
            salesMan.setStrategy(new StrategyB());
            // 展示促销活动
            salesMan.salesManShow();
    
            System.out.println("==============");
            // 圣诞节到了,使用圣诞节的促销活动
            salesMan.setStrategy(new StrategyC());
            // 展示促销活动
            salesMan.salesManShow();
        }
    }
    

    saída

    买一送一
    ==============
    满200元减50元
    ==============
    满1000元加一元换购任意200元以下商品
    

Vantagens e desvantagens

vantagem

  • Alternar livremente entre classes de estratégia
    • Como todas as classes de estratégia implementam a mesma interface, elas podem ser alternadas livremente.
  • fácil de expandir
    • Para adicionar uma nova estratégia, você só precisa adicionar uma classe de estratégia específica e basicamente não precisa alterar o código original, que está de acordo com o "princípio de abertura e fechamento".
  • Evite usar várias instruções de seleção condicional (caso contrário), incorpore totalmente a ideia de design orientado a objetos.

deficiência

  • Todas as classes de política precisam ser expostas ao mundo externo, e o cliente deve conhecer todas as classes de política e decidir qual usar.
  • O padrão de estratégia gerará muitas classes de estratégia e o número de objetos pode ser reduzido até certo ponto usando o padrão flyweight.

cenas a serem usadas

  • Quando um sistema precisa selecionar dinamicamente um dos vários algoritmos, cada algoritmo pode ser encapsulado em uma classe de estratégia.
  • Uma classe define vários comportamentos, e esses comportamentos aparecem na forma de várias declarações condicionais na operação dessa classe. Em vez dessas declarações condicionais, cada ramificação condicional pode ser movida para sua própria classe de estratégia.
  • Cada algoritmo no sistema é completamente independente um do outro e é necessário ocultar os detalhes de implementação do algoritmo específico do cliente.
  • Quando o sistema exige que os clientes que usam o algoritmo não conheçam os dados em que opera, o padrão de estratégia pode ser usado para ocultar as estruturas de dados associadas ao algoritmo.
  • A única diferença entre várias classes é que elas se comportam de maneira diferente.Você pode usar o modo de estratégia para selecionar dinamicamente o comportamento específico a ser executado em tempo de execução.

Análise de código-fonte JDK - Comparador

Comparatorpadrão de estratégia em . Existe um método na classe Arrays sort(), conforme abaixo:

public class Arrays{
    
    
    public static <T> void sort(T[] a, Comparator<? super T> c) {
    
    
        if (c == null) {
    
    
            sort(a);
        } else {
    
    
            if (LegacyMergeSort.userRequested)
                legacyMergeSort(a, c);
            else
                TimSort.sort(a, 0, a.length, c, null, 0, 0);
        }
    }
}

Arrays é uma classe de função do ambiente. O método sort pode passar uma nova estratégia para fazer com que os Arrays sejam classificados de acordo com esta estratégia. Por exemplo, a seguinte classe de teste.

public class demo {
    
    
    public static void main(String[] args) {
    
    

        Integer[] data = {
    
    12, 2, 3, 2, 4, 5, 1};
        // 实现降序排序
        Arrays.sort(data, new Comparator<Integer>() {
    
    
            public int compare(Integer o1, Integer o2) {
    
    
                return o2 - o1;
            }
        });
        System.out.println(Arrays.toString(data)); // [12, 5, 4, 3, 2, 2, 1]
    }
}

Aqui, quando chamamos o método sort de Arrays, o segundo parâmetro é o objeto de classe de subimplementação da interface Comparator. Portanto, Comparator atua como uma função de estratégia abstrata, enquanto a classe de subimplementação específica atua como uma função de estratégia concreta. As classes de função de ambiente (Arrays) devem conter referências a políticas abstratas a serem invocadas. Então, o método sort da classe Arrays usa o método na classe de subimplementação Comparator compare()? Vamos continuar a olhar para sort()o método da classe TimSort, o código é o seguinte:

class TimSort<T> {
    
    
    static <T> void sort(T[] a, int lo, int hi, Comparator<? super T> c,
                         T[] work, int workBase, int workLen) {
    
    
        assert c != null && a != null && lo >= 0 && lo <= hi && hi <= a.length;

        int nRemaining  = hi - lo;
        if (nRemaining < 2)
            return;  // Arrays of size 0 and 1 are always sorted

        // If array is small, do a "mini-TimSort" with no merges
        if (nRemaining < MIN_MERGE) {
    
    
            int initRunLen = countRunAndMakeAscending(a, lo, hi, c);
            binarySort(a, lo, hi, lo + initRunLen, c);
            return;
        }
        ...
    }   

    private static <T> int countRunAndMakeAscending(T[] a, int lo, int hi,Comparator<? super T> c) {
    
    
        assert lo < hi;
        int runHi = lo + 1;
        if (runHi == hi)
            return 1;

        // Find end of run, and reverse range if descending
        if (c.compare(a[runHi++], a[lo]) < 0) {
    
     // Descending
            while (runHi < hi && c.compare(a[runHi], a[runHi - 1]) < 0)
                runHi++;
            reverseRange(a, lo, runHi);
        } else {
    
                                  // Ascending
            while (runHi < hi && c.compare(a[runHi], a[runHi - 1]) >= 0)
                runHi++;
        }

        return runHi - lo;
    }
}

O código acima eventualmente será executado countRunAndMakeAscending()neste método. Podemos ver que o método é chamado neste método c.compare(), então ao chamar o método Arrays.sort, é passado apenas o objeto classe do método compare override específico, este também é um método que deve ser implementado por subclasses na interface Comparator. Esta é a personificação do padrão de estratégia.

Padrão de estratégia para pool de threads - estratégia de rejeição

Artigo de referência: Thread Pool - Explicação detalhada de ThreadPoolExecutor - Custom Thread Pool .

Acho que você gosta

Origin blog.csdn.net/weixin_53407527/article/details/128627989
Recomendado
Clasificación