Explicação detalhada dos padrões de design para desenvolvimento Android

Seis princípios de padrões de design

Antes de falar sobre os padrões de projeto comumente usados, primeiro apresente os seis princípios dos padrões de projeto: o princípio de responsabilidade única, o princípio aberto e fechado, o princípio de substituição interna, o princípio de inversão de dependência, o princípio Dimit e o princípio de isolamento de interface.

  Definição do princípio de responsabilidade única : no que diz respeito a uma classe, deve haver apenas uma razão para sua mudança. Em termos leigos, não devemos permitir que uma classe assuma muitas responsabilidades.

  Definição do princípio aberto e fechado : classes, módulos, funções, etc. devem ser expansíveis, mas não podem ser modificados. Aberto e fechado têm dois significados: um é aberto para expansão e o outro é fechado para modificação.

A   definição do princípio de substituição de Li : todas as referências à classe base (classe pai) devem ser capazes de usar de forma transparente os objetos de suas subclasses. O princípio de substituição de Richter nos diz que se um objeto de classe base for substituído por seu objeto de subclasse no software, o programa não produzirá erros ou exceções; o inverso não é verdadeiro. Se uma entidade de software usa um objeto de subclasse, então pode não ser capaz de usar o objeto da classe base.

  Definição do princípio de inversão de dependência : módulos de alto nível não devem depender de módulos de baixo nível, ambos devem depender de abstração. A abstração não deve depender de detalhes e os detalhes devem depender da abstração. 

Em Java, abstração se refere a uma interface ou classe abstrata, ambas as quais não podem ser instanciadas diretamente; os detalhes são a classe de implementação e os detalhes produzidos pela implementação da interface ou herdando a classe abstrata são os detalhes. O módulo de alto nível é o lado da chamada e o módulo de baixo nível é a classe de implementação específica. A manifestação do princípio de inversão de dependência em Java é que as dependências entre os módulos ocorrem por meio de abstração, e não há dependência direta entre as classes de implementação e as dependências são geradas por meio de interfaces ou classes abstratas. Se as classes e classes dependerem diretamente de detalhes, elas serão diretamente acopladas. Desta forma, ao modificar, o código dependente será modificado ao mesmo tempo, o que limita a escalabilidade.

O princípio Dimit  define: Uma entidade de software deve interagir com outras entidades o mínimo possível. Isso também é conhecido como o princípio do mínimo conhecimento.

Se um sistema for carregado com o princípio de Dimit, quando um dos módulos for modificado, afetará os outros módulos o menos possível.

  Definição do princípio de isolamento de interface : a dependência de uma classe em outra deve ser estabelecida na menor interface.

Estabeleça uma única interface, não crie uma interface enorme e inchada; tente refinar a interface tanto quanto possível, e há o mínimo de métodos possível na interface. Em outras palavras, precisamos estabelecer uma interface dedicada para cada classe, em vez de tentar estabelecer uma interface muito grande para todas as classes que dependem dela para chamar.

 

Classificação do padrão de design

Há um total de 23 padrões de projeto propostos pelo GoF, que são classificados de acordo com critérios de propósito e divididos em três categorias.

Existem 5 padrões de design criativo: padrão singleton, padrão de método de fábrica, padrão de fábrica abstrato, padrão de construtor e padrão de protótipo.

Existem 7 modos de design estrutural : modo adaptador, modo de decoração, modo de agente, modo de aparência, modo de ponte, modo de combinação e modo flyweight.

Existem 11 padrões de design comportamental : padrão de estratégia, padrão de método de template, padrão de observador, padrão de iterador, padrão de cadeia de responsabilidade, padrão de comando, padrão de memorando, padrão de estado, padrão de visitante, padrão intermediário e padrão de interpretador.

Além disso, com o desenvolvimento de padrões de design, muitos novos padrões de design surgiram: são modelo em escala, modelo de pool de objetos, modelo de trabalhador contratado, modelo de quadro-negro e modelo de objeto vazio.

 

Padrão de design criativo

O tipo de criação envolve padrões, como o nome sugere, está relacionado à criação de objetos, que inclui padrão singleton, padrão de método de fábrica, padrão de fábrica abstrato, padrão de construtor e padrão de protótipo. Embora o padrão de fábrica simples não seja o padrão de design de criação proposto pelo GoF, é útil entender o padrão de fábrica abstrato, portanto, o padrão de fábrica simples também será mencionado aqui.

Modo singleton

Definição: Certifique-se de que uma classe tenha apenas uma instância e forneça um ponto de acesso global para acessá-la.

6 maneiras de escrever o modo singleton

(1) Modo homem faminto

public class Singleton {

    instância Singleton estática privada = new Singleton ();

   particular Singleton () {

   }

   public static Singleton getInstance () {

       instância de retorno;

   }

}

Desta forma, a inicialização é completada quando a classe é carregada, de forma que o carregamento da classe é mais lento, mas a velocidade de obtenção do objeto é mais rápida. Este método é baseado no mecanismo de carregamento de classe e evita o problema de sincronização de vários threads. A instanciação é concluída quando a classe é carregada e o efeito do carregamento lento não é obtido. Se essa instância não tiver sido usada do início ao fim, haverá perda de memória.

(2) Modo homem preguiçoso (a discussão não é segura)

public class Singleton {

    instância Singleton estática privada;

    particular Singleton () {

    }

    public static Singleton getInstance () {

       if (instância == null) {

           instância = novo Singleton ();

       }

       instância de retorno;

    }

}

O modo lazy man declara um objeto estático, que é inicializado quando o usuário o chama pela primeira vez. Embora economize recursos, ele precisa ser instanciado quando é carregado pela primeira vez, a resposta é um pouco mais lenta e não funciona corretamente quando multithread.

(3) Modo lento (thread safety)

public class Singleton {

    instância Singleton estática privada;

    particular Singleton () {

    }

    public static synchronized Singleton getInstance () {

       if (instância == null) {

           instância = novo Singleton ();

       }

       instância de retorno;

    }

}

Essa maneira de escrever funciona bem em vários threads, mas precisa ser sincronizada sempre que o método getInstance é chamado. Desta vez, causa sobrecarga de sincronização desnecessária e, na maioria das vezes, não precisamos de sincronização. Portanto, este modo não é recomendado.

(4) Modo de verificação dupla (DCL)

public class Singleton {

    instância privada estática volátil Singleton;

    particular Singleton () {

    }

    public static Singleton getInstance () {

        if (instância == null) {

            synchronized (Singleton.class) {

                if (instância == null) {

                   instância = novo Singleton ();

                }

           }

            instância de retorno;

        }

    }

}

Desta forma, Singleton é julgado duas vezes no método getInstance: a primeira vez é para sincronização desnecessária e a segunda vez que a instância é criada quando Singleton é igual a null. Usar volátil aqui afetará o desempenho mais ou menos, mas considerando a correção do programa, vale a pena sacrificar esse desempenho. A vantagem do DCL é a alta utilização de recursos. O objeto singleton é instanciado quando getInstace é executado pela primeira vez, o que é altamente eficiente. A desvantagem é que a resposta é um pouco mais lenta quando carregada pela primeira vez e também tem certos defeitos em um ambiente de alta simultaneidade. Embora DCL resolva os problemas de consumo de recursos, sincronização redundante e segurança de thread até certo ponto, ele ainda falha em alguns casos, ou seja, o DCL falha. Recomenda-se substituir o DCL pelo modo singleton de classe interna estática.

(5) Modo singleton de classe interna estática

public class Singleton {

    Singleton privado () {}

   classe estática privada SingletonHolder {

       Singleton final estático privado sInstance = new Singleton ();

   }

   public static Singleton getInstance () {

      return SingletonHolder.sInstance;

   }

}

Quando a classe Singleton é carregada pela primeira vez, sInstance não é inicializado.Somente quando o método getInstance é chamado pela primeira vez, a máquina virtual carrega SingletonHolder e inicializa sInstance. Isso não apenas garante a segurança do segmento, mas também garante a exclusividade do Singleton. Portanto, é recomendável usar o padrão singleton de classe interna estática.

(6) Singleton de enumeração

public enum Singleton {

    INSTÂNCIA;

    public void doSomeThing () {

    }

}

A criação de instâncias de enumeração padrão é thread-safe e é um singleton em qualquer caso. Entre as várias implementações de modo singleton mencionadas acima, há um caso em que ele recriará o objeto, ou seja, a desserialização: escrever um objeto de instância singleton no disco e lê-lo de volta para obter uma instância. A operação de desserialização fornece o método readResolve, que permite aos desenvolvedores controlar a desserialização do objeto. Nos vários exemplos de métodos acima, se você quiser evitar que o objeto singleton seja desserializado para regenerar o objeto, você deve adicionar o seguinte método:

objeto privado readResolve () lança ObjectSreadmException {

    return singleton;

}

A vantagem do singleton de enumeração é sua simplicidade, mas a maioria do desenvolvimento de aplicativos raramente usa enumeração e sua legibilidade não é muito alta. Quanto à escolha de qual forma de modo singleton, depende do seu próprio projeto: se é um ambiente concorrente complexo ou se você precisa controlar o consumo de recursos de objetos singleton.

Use cenários de modo singleton:

Em um sistema, uma classe deve ter apenas um objeto e seus cenários de uso específicos são os seguintes:

Todo o projeto requer um ponto de acesso compartilhado ou dados compartilhados.

Para criar um objeto, são necessários muitos recursos, como acessar I / O ou recursos de banco de dados

Objeto de ferramenta.

 

Padrão de fábrica simples (padrão de método de fábrica estático)

Definição: o padrão de fábrica simples pertence ao padrão de criação, que também é chamado de padrão de método de fábrica estático, que é uma instância da classe de produto criada por um objeto de fábrica.

Existem as seguintes funções no modelo de fábrica simples:

Factory: classe de fábrica, é o núcleo do padrão de fábrica simples, que é responsável por implementar a lógica interna de criação de todas as instâncias. O método de criação de uma classe de produto da classe de fábrica pode ser chamado diretamente pelo mundo externo para criar o objeto de produto necessário.

IProduct: classe de produto abstrata, esta é a classe pai de todos os objetos criados pelo padrão de fábrica simples e é responsável por descrever as interfaces comuns compartilhadas por todas as instâncias.

Produzir: categorias específicas de produtos, esse é o objetivo do modelo de fábrica simples.

Categoria de produto abstrata

public abstract class Computer {

    resumo público void start ();

}

Categoria de produto específica

público calss LenovoComputer extends Computer {

    @Sobrepor

    public void start () {

        System.out.println ("inicialização do computador Lenovo");

    }

}

public calss HpComputer extends Computer {

    @Sobrepor

    public void start () {

        System.out.println ("Computador HP iniciado");

    }

}

public calss AsusComputer extends Computer {

    @Sobrepor

    public void start () {

        System.out.println ("Inicialização do Computador ASUS");

    }

}

Aula de fábrica

public class ComputerFactory {

    public static Computer createComputer (tipo String) {

        Computador mComputer = null;

        switch (tipo) {

            case "lenovo":

                 mComputer = novo LenovoComputer ();

                 pausa;

          case "hp":

                 mComputer = novo HpComputer ();

                 pausa;

           case "asus":

                 mComputer = novo AsusComputer ();

                 pausa;

        }

        return mComputer;

    }

}

O cliente chama a classe de fábrica

public class CreateComputer {

    public static void main (String [] args) {

        ComputerFactory.createComputer ("hp"). Start ();

    }

}

Cenários e vantagens e desvantagens de usar o modo de fábrica simples

cenas a serem usadas

A classe fábrica é responsável por criar menos objetos.

Os clientes precisam apenas saber os parâmetros passados ​​para a classe de fábrica e não precisam se preocupar com a lógica de criação de objetos.

Vantagens: Permite que os usuários obtenham instâncias de classe de objetos com base em parâmetros, evita a instanciação direta de classes e reduz o acoplamento.

Desvantagens: os tipos que podem ser instanciados foram determinados durante a compilação. Se você adicionar um novo tipo, será necessário modificar a fábrica, o que viola o princípio de aberto e fechado. A fábrica simples precisa saber todos os tipos a serem produzidos e não é adequada para uso quando há muitas subclasses ou muitos níveis de subclasses.

 

Padrão de método de fábrica

Definição: define uma interface para criar objetos e permite que as subclasses decidam qual classe instanciar. Os métodos de fábrica atrasam a instanciação de uma classe para suas subclasses.

Implementação simples do padrão de método de fábrica

Criar fábrica abstrata

public abstract class ComputerFactory {

    public abstract <T extends Computer> T createComputer (Class <T> clz);

}

Fábrica específica

public class GDComputerFactory extends ComputerFactory {

    @Sobrepor

    public <T extends Computer> T createComputer (Class <T> clz) {

         Computador computador = nulo;

         String classname = clz.getName ();

         experimentar {

            computer = (Computer) Class.forName (classname) .newInstance ();

         } catch (Exception e) {

             e.printStackTrace ();

         }

         return (T) computador;

    }

}

Chamada de cliente

public class Client {

    public static void main (String [] args) {

        ComputerFactory computerFactory = novo GDComputerFactory ();

        LenovoComputer mLenovoComputer = computerFactory.createComputer (LenovoComputer.class);

        mLenovoComputer.start ();

        HpComputer mHpComputer = computerFactory.createComputer (Hpomputer.class);

        mHpComputer.start ();

        AsusComputer mAsusComputer = computerFactory.createComputer (AsusComputer.class);

        mAsusComputer.start ();

    }

}

 

Modo Builder

O modo construtor, também conhecido como modo gerador, é um modo de criação que cria um objeto complexo, desacopla o processo de construção de um objeto complexo de seus componentes e separa o processo de construção da representação dos componentes.

Definição: separar a construção de um objeto complexo de sua representação, de forma que o mesmo processo de construção possa criar diferentes representações.

Existem as seguintes funções no modo de construtor:

Diretor: classe de diretor, responsável por organizar a ordem dos módulos existentes e, em seguida, notificar o Construtor para começar a construir.

Builder: classe Abstract Builder, padroniza a formação de produtos, geralmente implementada por subclasses.

ConcreteBuilder: construtor concreto, implementa todos os métodos definidos pela classe abstrata Builder e retorna um objeto construído.

Produto: categoria de produto.

Implementação simples do padrão builder

Crie categorias de produtos:

public class Computer {

    private String mCpu;

    private String mMainboard;

    private String mRam;

    public void setmCpu (String mCpu) {

       this.mCpu = mCpu;

    }

     public void setmMainboard (String mMainboard) {

        this.mMainboard = mMainboard;

    }

    public void setmRam (String mRam) {

       this.mRam = mRam;

    }

}

Crie uma classe Builder para padronizar a estrutura do produto

public abstract class Builder {

    public abstract void buildCpu (String cpu);

    public abstract void buildMainboard (String mainboard) ;;

    public abstract void buildRam (String ram);

    public abstract Computer create ();

}

 public class MoonComputerBuilder extends Builder {

    Computador privado mComputador = novo Computador ();

    @Sobrepor

     public void buildCpu (String cpu) {

        mComputer.setmCpu (cpu);

     }

     

    @Sobrepor

     public void buildMainboard (String mainboard) {

        mComputer.setmMainboard (cpu);

     }

     

    @Sobrepor

     public void buildRam (String ram) {

        mComputer.setmRam (ram);

     }

      @Sobrepor

      public Computer create () {

           return mComputer;

      }

}

Use classes de diretor para unificar o processo de montagem

public class Director {

    Construtor mBuild = null;

    Diretor público (Builder build) {

        this.mBuild = build;

    }

    public Computer createComputer (Stirng cpu, String mainboard, String ram) {

       this.mBuild.buildMainboard (placa-mãe);

       this.mBuild.buildCpu (cpu);

       this.mBuild.buildRam (ram);

       return mBuild.create ();

    }

}

O cliente chama a classe do diretor

public class CreateComputer {

    public static void main (String [] args) {

        Construtor mBuilder = new MoonComputerBuilder ();

        Diretor mDirector = novo Diretor (mBuilder);

        mDirector.createComputer ("i7-8700", "Core", "Lenovo DDR4");

    }

}

Cenários e vantagens e desvantagens de usar o modo construtor

cenas a serem usadas:

Quando o algoritmo para a criação de objetos complexos deve ser independente dos componentes do objeto e de como eles são montados.

O mesmo método, ordem de execução diferente, ao produzir resultados de eventos diferentes.

Vários componentes ou peças podem ser montados em um objeto, mas os resultados da execução são diferentes.

A categoria do produto é muito complexa, ou a sequência de chamada na categoria do produto é diferente e diferentes desempenhos são produzidos.

Ao criar alguns objetos complexos, a sequência de construção entre os componentes internos desses objetos é estável, mas os componentes internos dos objetos enfrentam mudanças complexas.

vantagem:

Usar o modo construtor pode evitar que o cliente conheça os detalhes da composição interna do produto.

As classes de construtor específicas são mutuamente independentes e fáceis de expandir.

Como o construtor específico é independente, ele pode refinar gradualmente o processo de construção sem qualquer impacto nos outros módulos.

Desvantagens:

Gere objetos Build redundantes e classes diretor.

 

 

 

 

 

 

 

 

 

 

 

 

 

Acho que você gosta

Origin blog.csdn.net/MYBOYER/article/details/107207655
Recomendado
Clasificación