Explicación detallada de los patrones de diseño para el desarrollo de Android

Seis principios de patrones de diseño

Antes de hablar sobre los patrones de diseño de uso común, primero introduzca los seis principios de los patrones de diseño. Son el principio de responsabilidad única, el principio abierto y cerrado, el principio de sustitución interna, el principio de inversión de dependencia, el principio Dimit y el principio de aislamiento de interfaz.

  Definición del principio de responsabilidad única : en lo que respecta a una clase, debe haber una sola razón para su cambio. En términos sencillos, no debemos permitir que una clase asuma demasiadas responsabilidades.

  Definición del principio abierto y cerrado : las clases, módulos, funciones, etc. deben ser ampliables, pero no modificables. Abierto y cerrado tienen dos significados: uno está abierto para expansión y el otro está cerrado para modificación.

La   definición del principio de sustitución de Li : todas las referencias a la clase base (clase principal) deben poder utilizar de forma transparente los objetos de sus subclases. El principio de sustitución de Richter nos dice que si un objeto de clase base se reemplaza con su objeto de subclase en el software, el programa no producirá ningún error o excepción; lo contrario no es cierto. Si una entidad de software utiliza un objeto de subclase, no poder utilizar el objeto de clase base.

  Definición del principio de inversión de dependencia : los módulos de alto nivel no deben depender de módulos de bajo nivel, ambos deben depender de la abstracción. La abstracción no debe depender de los detalles y los detalles deben depender de la abstracción. 

En Java, la abstracción se refiere a una interfaz o una clase abstracta, de las cuales no se pueden instanciar directamente; los detalles son la clase de implementación y los detalles producidos al implementar la interfaz o heredar la clase abstracta son los detalles. El módulo de alto nivel es el lado de la llamada y el módulo de bajo nivel es la clase de implementación específica. La manifestación del principio de inversión de dependencias en Java es que las dependencias entre módulos ocurren a través de la abstracción, y no hay dependencia directa entre clases de implementación, y las dependencias se generan a través de interfaces o clases abstractas. Si las clases y las clases dependen directamente de los detalles, se combinarán directamente. De esta forma, al modificar, el código dependiente se modificará al mismo tiempo, lo que limita la escalabilidad.

El principio Dimit  define: Una entidad de software debe interactuar con otras entidades lo menos posible. Esto también se conoce como el principio de conocimiento mínimo.

Si un sistema se carga con el principio de Dimit, cuando se modifica uno de los módulos, afectará lo menos posible a los otros módulos.

  Definición del principio de aislamiento de interfaz : la dependencia de una clase de otra debe establecerse en la interfaz más pequeña.

Establezca una interfaz única, no cree una interfaz enorme e inflada; intente refinar la interfaz tanto como sea posible, y hay tan pocos métodos en la interfaz como sea posible. En otras palabras, necesitamos establecer una interfaz dedicada para cada clase, en lugar de intentar establecer una interfaz muy grande para todas las clases que dependen de ella para llamar.

 

Clasificación de patrones de diseño

Hay un total de 23 patrones de diseño propuestos por GoF, que se clasifican según criterios de propósito y se dividen en tres categorías.

Hay 5 patrones de diseño creativo: patrón singleton, patrón de método de fábrica, patrón de fábrica abstracto, patrón de constructor y patrón de prototipo.

Hay 7 modos de diseño estructural : modo adaptador, modo decoración, modo agente, modo apariencia, modo puente, modo combinado y modo peso mosca.

Hay 11 patrones de diseño de comportamiento : patrón de estrategia, patrón de método de plantilla, patrón de observador, patrón de iterador, patrón de cadena de responsabilidad, patrón de comando, patrón de memo, patrón de estado, patrón de visitante, patrón de intermediario y patrón de intérprete.

Además, con el desarrollo de patrones de diseño, han surgido muchos patrones de diseño nuevos: modelo a escala, modelo de grupo de objetos, modelo de trabajador contratado, modelo de pizarra y modelo de objeto vacío.

 

Patrón de diseño creativo

El tipo de creación involucra patrones, como su nombre indica, está relacionado con la creación de objetos, que incluye patrón singleton, patrón de método de fábrica, patrón de fábrica abstracto, patrón de constructor y patrón de prototipo. Aunque el patrón de fábrica simple no es el patrón de diseño de creación propuesto por GoF, es útil comprender el patrón de fábrica abstracto, por lo que el patrón de fábrica simple también se mencionará aquí.

Modo singleton

Definición: asegúrese de que una clase tenga solo una instancia y proporcione un punto de acceso global para acceder a ella.

6 formas de escribir en modo singleton

(1) Modo de hombre hambriento

clase pública Singleton {

    instancia privada de Singleton estático = nuevo Singleton ();

   Singleton privado () {

   }

   public static Singleton getInstance () {

       instancia de retorno;

   }

}

De esta forma, la inicialización se completa cuando se carga la clase, por lo que la carga de la clase es más lenta, pero la velocidad de obtención del objeto es más rápida. Este método se basa en el mecanismo de carga de clases y evita el problema de sincronización de varios subprocesos. La instanciación se completa cuando se carga la clase y no se logra el efecto de carga diferida. Si esta instancia no se ha utilizado de principio a fin, provocará una pérdida de memoria.

(2) Modo de hombre perezoso (el hilo no es seguro)

clase pública Singleton {

    instancia privada estática de Singleton;

    Singleton privado () {

    }

    public static Singleton getInstance () {

       si (instancia == nulo) {

           instancia = nuevo Singleton ();

       }

       instancia de retorno;

    }

}

El modo de hombre perezoso declara un objeto estático, que se inicializa cuando el usuario lo llama por primera vez. Aunque esto ahorra recursos, es necesario crear una instancia cuando se carga por primera vez, la respuesta es un poco más lenta y no funciona correctamente cuando se usa multiproceso.

(3) Modo perezoso (seguridad de subprocesos)

clase pública Singleton {

    instancia privada estática de Singleton;

    Singleton privado () {

    }

    getInstance () {público estático sincronizado Singleton

       si (instancia == nulo) {

           instancia = nuevo Singleton ();

       }

       instancia de retorno;

    }

}

Esta forma de escritura funciona bien en varios subprocesos, pero debe sincronizarse cada vez que se llama al método getInstance. Esta vez provoca una sobrecarga de sincronización innecesaria, y la mayoría de las veces no necesitamos sincronización. Por lo tanto, no se recomienda este modo.

(4) Modo de doble comprobación (DCL)

clase pública Singleton {

    instancia privada estática volátil Singleton;

    Singleton privado () {

    }

    public static Singleton getInstance () {

        si (instancia == nulo) {

            sincronizado (Singleton.class) {

                si (instancia == nulo) {

                   instancia = nuevo Singleton ();

                }

           }

            instancia de retorno;

        }

    }

}

De esta forma, Singleton se juzga dos veces en el método getInstance: la primera vez es por sincronización innecesaria y la segunda vez se crea la instancia cuando Singleton es igual a nulo. El uso de volatile aquí afectará más o menos el rendimiento, pero considerando la corrección del programa, vale la pena sacrificar este rendimiento. La ventaja de DCL es la alta utilización de recursos. Se crea una instancia del objeto singleton cuando getInstace se ejecuta por primera vez, lo cual es muy eficiente. La desventaja es que la respuesta es un poco más lenta cuando se carga por primera vez y también tiene ciertos defectos en un entorno de alta concurrencia. Aunque DCL resuelve los problemas de consumo de recursos, sincronización redundante y seguridad de subprocesos hasta cierto punto, todavía falla en algunos casos, es decir, falla DCL. Se recomienda reemplazar DCL con el modo singleton de clase interna estática.

(5) Modo singleton de clase interna estática

clase pública Singleton {

    Singleton privado () {}

   clase estática privada SingletonHolder {

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

   }

   public static Singleton getInstance () {

      return SingletonHolder.sInstance;

   }

}

Cuando la clase Singleton se carga por primera vez, sInstance no se inicializa. Solo cuando se llama al método getInstance por primera vez, la máquina virtual carga SingletonHolder e inicializa sInstance. Esto no solo garantiza la seguridad de los hilos, sino que también garantiza la singularidad de Singleton. Por lo tanto, se recomienda utilizar el patrón singleton de clase interna estática.

(6) Singleton de enumeración

public enum Singleton {

    EJEMPLO;

    public void doSomeThing () {

    }

}

La creación de instancias de enumeración predeterminadas es segura para subprocesos y es un singleton en cualquier caso. Entre las varias implementaciones del modo singleton mencionadas anteriormente, hay un caso en el que recreará el objeto, es decir, la deserialización: escriba un objeto de instancia singleton en el disco y vuelva a leerlo para obtener una instancia. La operación de deserialización proporciona el método readResolve, que permite a los desarrolladores controlar la deserialización del objeto. En los varios ejemplos de métodos anteriores, si desea evitar que el objeto singleton se deserialice para regenerar el objeto, debe agregar el siguiente método:

El objeto privado readResolve () lanza ObjectSreadmException {

    retorno singleton;

}

La ventaja del singleton de enumeración es su simplicidad, pero la mayoría de los desarrollos de aplicaciones rara vez utilizan enumeración y su legibilidad no es muy alta. En cuanto a la elección de qué forma de modo singleton, depende de su proyecto en sí: si es un entorno concurrente complejo o si necesita controlar el consumo de recursos de los objetos singleton.

Utilice escenarios del modo singleton:

En un sistema, se requiere que una clase tenga y solo un objeto, y sus escenarios de uso específicos son los siguientes:

Todo el proyecto requiere un punto de acceso compartido o datos compartidos.

Crear un objeto requiere demasiados recursos, como acceder a E / S o recursos de base de datos

Objeto de herramienta.

 

Patrón de fábrica simple (patrón de método de fábrica estático)

Definición: El patrón de fábrica simple pertenece al patrón de creación, que también se denomina patrón de método de fábrica estático, que es una instancia de la clase de producto que crea un objeto de fábrica.

Existen los siguientes roles en el modelo de fábrica simple:

Fábrica: clase de fábrica, este es el núcleo del patrón de fábrica simple, que es responsable de implementar la lógica interna de creación de todas las instancias. El mundo exterior puede llamar directamente al método de creación de una clase de producto de la clase de fábrica para crear el objeto de producto requerido.

IProduct: clase de producto abstracto, esta es la clase padre de todos los objetos creados por el patrón de fábrica simple, y es responsable de describir las interfaces comunes compartidas por todas las instancias.

Producir: Categorías de productos específicas, este es el objetivo del modelo de fábrica simple.

Categoría de producto abstracto

Computadora de clase abstracta pública {

    inicio vacío público abstracto ();

}

Categoría de producto específica

calss público LenovoComputer extiende Computer {

    @Anular

    inicio vacío público () {

        System.out.println ("Inicio de la computadora Lenovo");

    }

}

public calss HpComputer extiende Computer {

    @Anular

    inicio vacío público () {

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

    }

}

public calss AsusComputer extiende Computer {

    @Anular

    inicio vacío público () {

        System.out.println ("Inicio de la computadora ASUS");

    }

}

Clase de fábrica

public class ComputerFactory {

    public static Computer createComputer (tipo de cadena) {

        Computadora mComputer = null;

        cambiar (tipo) {

            caso "lenovo":

                 mComputer = nuevo LenovoComputer ();

                 romper;

          caso "hp":

                 mComputer = nuevo HpComputer ();

                 romper;

           caso "asus":

                 mComputer = nuevo AsusComputer ();

                 romper;

        }

        return mComputer;

    }

}

El cliente llama a la clase de fábrica

clase pública CreateComputer {

    public static void main (String [] args) {

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

    }

}

Escenarios y ventajas y desventajas de usar el modo de fábrica simple

escenas que se utilizarán

La clase de fábrica es responsable de crear menos objetos.

Los clientes solo necesitan conocer los parámetros pasados ​​a la clase de fábrica y no necesitan preocuparse por la lógica de la creación de objetos.

Ventajas: Permitir a los usuarios obtener instancias de clase de objetos basados ​​en parámetros, evitar la instanciación directa de clases y reducir el acoplamiento.

Desventajas: Los tipos de los que se pueden crear instancias se han determinado durante la compilación. Si agrega un nuevo tipo, debe modificar la fábrica, lo que viola el principio de abierto y cerrado. La fábrica simple necesita conocer todos los tipos que se van a producir y no es adecuada para su uso cuando hay demasiadas subclases o demasiados niveles de subclase.

 

Patrón de método de fábrica

Definición: Defina una interfaz para crear objetos y deje que las subclases decidan qué clase instanciar. Los métodos de fábrica retrasan la instanciación de una clase a sus subclases.

Implementación simple del patrón de método de fábrica

Crea una fábrica abstracta

clase pública abstracta ComputerFactory {

    resumen público <T extiende Computadora> T createComputer (Clase <T> clz);

}

Fábrica específica

La clase pública GDComputerFactory extiende ComputerFactory {

    @Anular

    public <T extiende Computadora> T createComputer (Class <T> clz) {

         Computadora computadora = nulo;

         String classname = clz.getName ();

         tratar {

            computadora = (Computadora) Class.forName (classname) .newInstance ();

         } captura (Excepción e) {

             e.printStackTrace ();

         }

         retorno (T) computadora;

    }

}

Llamada del cliente

Cliente de clase pública {

    public static void main (String [] args) {

        ComputerFactory computerFactory = nuevo 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 constructor

El modo constructor también se conoce como modo generador, es un modo de creación que crea un objeto complejo, desacopla el proceso de construcción de un objeto complejo de sus componentes y separa el proceso de construcción de la representación de los componentes.

Definición: Separar la construcción de un objeto complejo de su representación, para que un mismo proceso de construcción pueda crear diferentes representaciones.

Existen los siguientes roles en el modo de constructor:

Director: clase de director, responsable de organizar el orden de los módulos existentes y luego notificar al constructor que comience a construir.

Builder: clase Abstract Builder, estandariza la formación de productos, generalmente implementada por subclases.

ConcreteBuilder: constructor de concreto, implementa todos los métodos definidos por la clase Builder abstracto y devuelve un objeto construido.

Producto: categoría de producto.

Implementación simple del patrón de construcción

Crear categorías de productos:

Computadora de clase pública {

    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;

    }

}

Crea una clase Builder para estandarizar la estructura del producto.

Generador público de clases abstractas {

    public abstract void buildCpu (String cpu);

    public abstract void buildMainboard (String mainboard) ;;

    public abstract void buildRam (String ram);

    resumen público Computadora create ();

}

 MoonComputerBuilder de clase pública extiende Builder {

    computadora privada mComputer = nueva computadora ();

    @Anular

     public void buildCpu (String cpu) {

        mComputer.setmCpu (cpu);

     }

     

    @Anular

     public void buildMainboard (String mainboard) {

        mComputer.setmMainboard (cpu);

     }

     

    @Anular

     public void buildRam (String ram) {

        mComputer.setmRam (ram);

     }

      @Anular

      computadora pública create () {

           return mComputer;

      }

}

Utilice clases de director para unificar el proceso de ensamblaje

Director de clase pública {

    Constructor mBuild = null;

    director público (compilación del constructor) {

        this.mBuild = construir;

    }

    public Computer createComputer (Stirng cpu, placa base String, ram String) {

       this.mBuild.buildMainboard (placa base);

       this.mBuild.buildCpu (cpu);

       this.mBuild.buildRam (ram);

       return mBuild.create ();

    }

}

El cliente llama a la clase de director

clase pública CreateComputer {

    public static void main (String [] args) {

        Constructor mBuilder = new MoonComputerBuilder ();

        Director mDirector = nuevo Director (mBuilder);

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

    }

}

Escenarios y ventajas y desventajas de usar el modo constructor

escenas a utilizar:

Cuando el algoritmo para crear objetos complejos debe ser independiente de los componentes del objeto y cómo se ensamblan.

El mismo método, diferente orden de ejecución, cuando se producen diferentes resultados de eventos.

Se pueden ensamblar varios componentes o partes en un objeto, pero los resultados de ejecución son diferentes.

La categoría de producto es muy compleja, o la secuencia de llamadas en la categoría de producto es diferente y se producen diferentes rendimientos.

Al crear algunos objetos complejos, la secuencia de construcción entre los componentes internos de estos objetos es estable, pero los componentes internos de los objetos enfrentan cambios complejos.

ventaja:

El uso del modo constructor puede evitar que el cliente conozca los detalles de la composición interna del producto.

Las clases de constructores específicas son mutuamente independientes y fáciles de expandir.

Dado que el constructor específico es independiente, puede refinar gradualmente el proceso de construcción sin ningún impacto en otros módulos.

Desventajas:

Genere objetos de construcción y clases de director redundantes.

 

 

 

 

 

 

 

 

 

 

 

 

 

Supongo que te gusta

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