Patrón de decorador de patrones de diseño de Java (Patrón de decorador)

1. ¿Qué es un patrón de diseño? Un
patrón de diseño se refiere a una solución que ha sido verificada durante el proceso de desarrollo de software para resolver problemas recurrentes y específicos en un entorno específico. Se puede utilizar para mejorar la reutilización, el mantenimiento, la legibilidad, la solidez y la seguridad del código. En 1995, GoF (Gang of Four, Gang of Four) coeditó el libro "Design Patterns: The Foundation of Reusable Object-Oriented Software", que incluía un total de 23 patrones de diseño. Desde entonces, ha establecido un hito líder , conocido como "Modo de diseño GoF".
Clasificación:
A. Modo de creación: modo singleton, modo abstracto de fábrica, modo constructor, modo fábrica, modo prototipo.
b. Modo estructural: modo adaptador, modo puente, modo decoración, modo combinación, modo apariencia, modo peso mosca, modo proxy.
c. Modo de comportamiento: modo de método de plantilla, modo de comando, modo de iterador, modo de observador, modo de mediador, modo de nota, modo de intérprete (modo de intérprete), modo de estado, modo de estrategia, modo de cadena de responsabilidad (modo de cadena de responsabilidad), modo de visitante .

2. Patrón de decorador (Patrón de decorador) El
patrón de decorador asigna dinámicamente más responsabilidades a un objeto de una manera que es transparente para el usuario. En otras palabras, el cliente no siente ninguna diferencia entre el objeto antes y después de la decoración.
El diagrama de clases del
Inserte la descripción de la imagen aquí
patrón de decorador es el siguiente: los roles en el patrón de decoración son:
• Componente: componente abstracto, la clase padre común al decorador y al decorado, es una interfaz o clase abstracta utilizada para definir el comportamiento básico
• ConcreteComponent: define Object concreto, es decir, decorador
• Decorador: Decorador abstracto, heredado de Component, y extiende ConcreteComponent de la clase externa.
• ConcreteDecorator: decorador de hormigón, utilizado para ampliar los componentes abstractos de ConcreteComponent

public interface Component {
    
    public void sampleOperation();
    
}

Decorado

public class ConcreteComponent implements Component {
    @Override
    public void sampleOperation() {
        // 写相关的业务代码
    }
}

Decorador abstracto

public class Decorator implements Component{
    private Component component;
    
    public Decorator(Component component){
        this.component = component;
    }
    @Override
    public void sampleOperation() {
        // 委派给构件
        component.sampleOperation();
    }   
}

Decorador específico

public class ConcreteDecoratorA extends Decorator {
    public ConcreteDecoratorA(Component component) {
        super(component);
    }
    
    @Override
    public void sampleOperation() {
      // 写相关的业务代码
   super.sampleOperation();
     // 写相关的业务代码
    }
}

3. Demostración del patrón del decorador.
Montamos un puesto móvil para vender pasteles de mano. Nuestros pasteles de mano son ricos en contenido. Puedes agregar huevos, jamón, salsa de tomate, etc., pero si agregas diferentes ingredientes, necesitas añadir dinero ¿Cómo calcular dinámicamente este precio? Usando el modo decorador, nuestro puesto es un componente abstracto , el pastel de mano es el decorador , la salchicha de jamón de huevo, etc. son los decoradores específicos, y la salchicha de jamón de huevo, etc., colectivamente llamamos a los ingredientes decoradores abstractos .
Primero observe el diagrama de clases de nuestro ejemplo:
Inserte la descripción de la imagen aquí
implementación de código:
1. Componente abstracto-parada

/**
 * @Author: huangguopan
 * @Date: 2019/7/8 13:38
 * @Description: 抽象构件  流动摊子
 */
public interface Store {
    //商品描述
    String desc();
    //价格
    double cost();
}

2. El pastel de manos adornadas

/**
 * @Author: huangguopan
 * @Date: 2019/7/8 13:38
 * @Description: 具体构件  手抓饼
 */
public class Shouzhuabing {
    public String desc() {
        return "我是一个手抓饼,";
    }
    public double cost() {
        return 5;
    }
}

3. Decorador abstracto - ingredientes

/**
 * @Author: huangguopan
 * @Date: 2019/7/8 13:45
 * @Description:  抽象装饰角色  配料
 */
public class Peiliao extends Shouzhuabing {
    Shouzhuabing shouzhuabing;
    public Peiliao(Shouzhuabing shouzhuabing) {
        this.shouzhuabing = shouzhuabing;
    }
    @Override
    public String desc() {
        return shouzhuabing.desc();
    }
    @Override
    public double cost() {
        return shouzhuabing.cost();
    }
}

3. Huevos decoradores específicos

/**
 * @Author: huangguopan
 * @Date: 2019/7/8 13:39
 * @Description:  具体装饰  鸡蛋
 */
public class Jidan extends Peiliao {
    public Jidan(Shouzhuabing shouzhuabing) {
        super(shouzhuabing);
    }
    @Override
    public String desc() {
        return shouzhuabing.desc()+"加鸡蛋";
    }
    @Override
    public double cost() {
        return shouzhuabing.cost()+1;
    }
}

4. Embutido de decorador específico

/**
 * @Author: huangguopan
 * @Date: 2019/7/8 13:39
 * @Description: 具体装饰  火腿肠
 */
public class Huotuichang extends Peiliao {
    public Huotuichang(Shouzhuabing shouzhuabing) {
        super(shouzhuabing);
    }
    String shouroujing() {
        return "我加了瘦肉精";
    }
    @Override
    public String desc() {
        return shouzhuabing.desc()+"加火腿肠";
    }
    @Override
    public double cost() {
        return shouzhuabing.cost()+1;
    }
}

5. Decorador específico - salsa de tomate

/**
 * @Author: huangguopan
 * @Date: 2019/7/8 13:39
 * @Description: 具体装饰  番茄酱
 */
public class Fanqiejiang extends Peiliao {
    public Fanqiejiang(Shouzhuabing shouzhuabing) {
        super(shouzhuabing);
    }
    @Override
    public String desc() {
        return shouzhuabing.desc()+"加番茄酱";
    }
    @Override
    public double cost() {
        return shouzhuabing.cost()+1;
    }
}

6. Categoría de prueba:

/**
 * @Author: huangguopan
 * @Date: 2019/7/8 13:51
 * @Description:
 */
public class TestDecorator {
    public static void main(String[] args) {
        Store store = new Shouzhuabing();
        //单层装饰-只加火腿肠
        Store huotuichang = new Huotuichang(store);
        System.out.println(huotuichang.desc());
        System.out.println(huotuichang.cost());
        //双层装饰--加鸡蛋和火腿肠
        Store jidanHuotui = new Jidan(new Huotuichang(store));
        System.out.println(jidanHuotui.desc());
        System.out.println(jidanHuotui.cost());
    }
}

resultado:
Inserte la descripción de la imagen aquí

4. Simplificación del patrón del decorador En la
mayoría de los casos, la implementación del patrón del decorador es más simple que el ejemplo esquemático dado anteriormente.
Si solo hay una clase ConcreteComponent, entonces puede considerar eliminar la clase abstracta Component (interfaz) y usar Decorator como una subclase ConcreteComponent. Como se muestra en la siguiente figura: La
versión simplificada del diagrama de clases es la siguiente:
Inserte la descripción de la imagen aquí
Use la versión simplificada del ejemplo ahora para ilustrar : Si mi puesto móvil solo vende pasteles recogidos a mano, se puede simplificar si no vende otros artículos como tortitas y patatas fritas.
Inserte la descripción de la imagen aquí

Requisitos dinámicos: Por
ejemplo, el usuario se queja de que los ingredientes de mi pastel de mano son muy pocos y necesito ir al supermercado a agregar algunos ingredientes, como hilo de carne, pepino, etc., no necesito modificar la mano pastel u otro código de ingredientes, solo hereda el anterior Los ingredientes están bien. En otras palabras, para agregar un nuevo decorador, solo necesito heredar el decorador abstracto, que no es intrusivo a la clase anterior y cumple con el principio de apertura y cierre.
Requisitos de transparencia: La transparencia del
modo decorador al cliente requiere que el programa no declare una variable de tipo ConcreteComponent, sino una variable de tipo Component.
Usando el ejemplo de ahora, debo decir que estoy vendiendo pasteles de mano en lugar de ingredientes, no huevos o similares.
Por ejemplo:

Shouzhuabing shouzhuabing = new Shouzhuabing();
        
Shouzhuabing huotuichang = new Huotuichang(shouzhuabing);

En vez de:

Huotuichang huotuichang = new Huotuichang(shouzhuabing);
Jidan jidan = new Jidan(shouzhuabing);

Patrón de decorador translúcido
Sin embargo, los patrones de decorador puro son difíciles de encontrar. El propósito del patrón de decorador es mejorar el rendimiento de la clase considerada sin cambiar la interfaz. Al mejorar el desempeño, a menudo es necesario establecer nuevos métodos públicos. Como en el ejemplo anterior, cuando el cliente quiera agregar ingredientes, especifique el huevo que se va a marinar o freír. Este es un nuevo método de agregar huevos. El padre no lo sabe, por lo que debe transformarse hacia abajo.

Shouzhuabing shouzhuabing = new Shouzhuabing();

// Soy un tirano local con huevos estofados

Shouzhuabing ludan = new Jidan(shouzhuabing);
System.out.println(((Jidan) ludan).addLudan());

5. Aplicación del patrón de decorador en el flujo de IO de Java
La aplicación más famosa del patrón de decorador en el lenguaje Java es el diseño de la biblioteca estándar de I / O de Java.
Dado que la biblioteca de E / S de Java requiere varias combinaciones de muchas propiedades, si estas propiedades se logran por herencia, entonces cada combinación requiere una clase, lo que hará que aparezcan una gran cantidad de clases con propiedades repetidas. Y en el modo decorador, podemos ver este código:

new BufferedReader(new InputStreamReader(instream, encoding));)

Se puede ver que convertimos un flujo de bytes en un flujo de caracteres y agregamos almacenamiento en búfer para mejorar la eficiencia.
El diagrama de clases de la biblioteca de E / S de Java es el siguiente. Debido a que hay muchos objetos de E / S de Java, solo se dibuja la parte InputStream:
Inserte la descripción de la imagen aquí
De acuerdo con la figura anterior, podemos ver:
● Componente abstracto (Componente): Reproducido por InputStream. Esta es una clase abstracta que proporciona una interfaz unificada para varios subtipos.
● Decorado (ConcreteComponent): Reproducido por ByteArrayInputStream, FileInputStream, PipedInputStream, StringBufferInputStream y otras clases. Implementan la interfaz especificada por el rol del componente abstracto.
● Decorador abstracto (Decorador): interpretado por FilterInputStream. Implementa la interfaz especificada por InputStream. La función es encapsular otros flujos de entrada y proporcionarles funciones adicionales, a saber, decoradores abstractos.
● Decorador de hormigón (ConcreteDecorator): jugado por varias clases, a saber, BufferedInputStream, DataInputStream, y dos clases poco utilizadas, LineNumberInputStream y PushbackInputStream. Es decir, el decorador específico.
Por ejemplo, la función de BufferedInputStream es "proporcionar funciones de almacenamiento en búfer para flujos de entrada, así como funciones mark () y reset ()". Puede ver que esos dos nuevos métodos solo están disponibles para subclases, y la clase principal no lo sé, es decir, por encima de nosotros. El mencionado traslúcido.

6. Resuma
las ventajas del modo de decoración
(1) El propósito del modo de decoración y la relación de herencia es extender la función del objeto, pero el modo de decoración puede proporcionar más flexibilidad que la herencia. El modo de decoración permite que el sistema decida dinámicamente "pegar" una "decoración" necesaria o eliminar una "decoración" innecesaria.
(2) Mediante el uso de diferentes tipos de decoración específicos y la permutación y combinación de estos tipos de decoración, se pueden crear muchas combinaciones de diferentes comportamientos.
Desventajas del
patrón de decoración El uso del patrón de decoración producirá más objetos que el uso de la herencia. Más objetos dificultarán la resolución de problemas, especialmente si estos objetos se parecen.
Referencia:
https://www.jianshu.com/p/d7f20ae63186

Supongo que te gusta

Origin blog.csdn.net/u010857795/article/details/104697376
Recomendado
Clasificación