Patrón de diseño estructural: patrón de decorador

Directorio de columnas de patrón de diseño

Patrones de diseño creacional: Patrón Singleton/Patrón de fábrica/
Patrón de diseño de comportamiento de fábrica abstracta: Patrón de diseño de plantilla/Patrón de diseño de observador/Patrón de diseño de estrategia Patrón de diseño estructural: Modo
decorador

Clasificación de patrones de diseño

Los patrones de diseño se pueden dividir en tres tipos: patrones de diseño creacional, patrones de diseño estructural y patrones de diseño de comportamiento.

Patrones de diseño creacional: estos patrones involucran el mecanismo de creación de objetos , incluido el patrón de fábrica simple, el patrón de método de fábrica, el patrón de fábrica abstracto, el patrón de singleton, el patrón de constructor y el patrón de prototipo.

Patrones de diseño estructural: estos patrones involucran la combinación de clases y objetos , incluido el patrón de adaptador, el patrón de puente, el patrón de composición, el patrón de decorador, el patrón de apariencia, el patrón de peso ligero y el patrón de proxy.

Patrones de diseño de comportamiento: estos patrones involucran comunicación e interacción entre objetos , incluido el patrón de cadena de responsabilidad, patrón de comando, patrón de intérprete, patrón de iterador, patrón de intermediario, patrón de memo, patrón de observador , patrón de estado, patrón de estrategia , patrón de método de plantilla y patrón de visitante.

Este artículo es un resumen de decoradores y patrones de diseño combinados en patrones de diseño estructural. La definición de cada patrón de diseño es relativamente oscura, puede mirar directamente el código para comprender.

Principios de diseño de patrones de diseño

Inversión de dependencia : los módulos de alto nivel no deben depender de los módulos de bajo nivel, ambos deben depender de la abstracción; la abstracción no debe depender de una implementación concreta, la implementación concreta debe depender de la abstracción; (solo recuerde confiar en la abstracción ) .
Abierta y cerrada : una clase debe estar abierta a la extensión (combinación y herencia) y cerrada a la modificación;
orientada a la interfaz : el tipo de variable no se declara como una clase concreta específica, sino que se declara como una interfaz;
el programa cliente no necesita Conozca los detalles del tipo de objeto, solo necesita conocer la interfaz del objeto;
reduzca las dependencias de cada parte del sistema, para realizar el esquema de diseño tipo de "alta cohesión y bajo acoplamiento"; ( recuerde solo exponer la interfaz, solo llamar a la interfaz) .
Encapsular el punto de cambio : separar el punto estable del punto de cambio, expandir y modificar el punto de cambio; separar los niveles de implementación del punto estable y el punto de cambio; responsabilidad única : una clase debe tener solo una razón para su cambio; (que es decir, no debe haber demasiados puntos de cambio) . Sustitución de Liskov : el subtipo debe poder reemplazar su tipo principal; ocurre principalmente cuando la subclase anula la implementación de la clase principal y el programa que originalmente usó el tipo principal puede tener errores; el método de la clase principal está cubierto pero la responsabilidad del método de la clase principal no está implementada; (es decir, la subclase puede anular el método de la clase principal, pero se deben garantizar las funciones necesarias de la clase principal) . Aislamiento de interfaz : los clientes no deben verse obligados a depender de métodos que no usan;generalmente se usa para tratar con una clase con más interfaces, y estas interfaces implican muchas responsabilidades;los clientes no deben confiar en interfaces que no necesitan. La dependencia de una clase de otra clase debe basarse en la interfaz más pequeña. Composición sobre herencia






: El grado de acoplamiento de la herencia es alto, el grado de acoplamiento de la composición es bajo;

patrón decorador

Agregue dinámicamente algunas responsabilidades adicionales a los objetos.La decoración es más flexible que la subclasificación en términos de agregar funcionalidad.

Use un ejemplo de cómo calcular el costo de un plato (incluidos los alimentos y varios condimentos) para ilustrar este patrón de diseño:

En los restaurantes, debe calcular el costo de los alimentos, como fideos y varios condimentos:

#include <iostream>
#include <string>

using namespace std;

// 食品类
class Food {
    
    
protected:
	string des;
	double price;

public:
	virtual double cost() = 0;
	string getDes() {
    
    
		return des;
	}
	void setDes(string des) {
    
    
		this->des = des;
	}
	double getPrice() {
    
    
		return price;
	}
	void setPrice(double price) {
    
    
		this->price = price;
	}
};

// 面条类
class Noodles : public Food {
    
    
public:
	double cost() override {
    
    
		return getPrice();
	}
};

// 中式面条类
class ChineseNoodles : public Noodles {
    
    
public:
	ChineseNoodles() {
    
    
		setDes("中式面条");
		setPrice(25.00);
	}
};

// 装饰器类
class Decorator : public Food {
    
    
protected:
	Food* desFood;

public:
	Decorator(Food* desFood) {
    
    
		this->desFood = desFood;
	}
	double cost() override {
    
    
		cout << desFood->getDes() << "价格:" << desFood->getPrice() << "  配料如下:"
			<< getDes() << "  价格:" << getPrice() << "  总价" << (getPrice() + desFood->cost()) << endl;
		return getPrice() + desFood->cost();
	}
};

// 孜然类
class Cumin : public Decorator {
    
    
public:
	Cumin(Food* desFood) : Decorator(desFood) {
    
    
		setDes("孜然");
		setPrice(2.00);
	}
};
// 胡椒类
class Peper : public Decorator {
    
    
public:
	Peper(Food* desFood) : Decorator(desFood) {
    
    
		setDes("胡椒");
		setPrice(3.00);
	}
};

int main() {
    
    
	// 先定义一个被装饰者,返回对象要为最顶层的对象,这样被装饰者才能接受
	Food* noodles = new ChineseNoodles();
	// 定义一个装饰者对象
	Food* cumin = new Cumin(noodles);
	// 输出为:中式面条价格:25配料如下:孜然价格:2总价27
	cout << "-----------面条+孜然------------------------" << endl;
	cumin->cost();
	cout << "-----------面条+胡椒------------------------" << endl;
	Food* peper = new Peper(noodles);
	peper->cost();
	cout << "-----------面条+胡椒+孜然------------------------" << endl;
	peper = new Peper(cumin);
	cout << "面条+胡椒+孜然价格:" <<peper->cost();

	delete cumin;
	delete noodles;
	delete peper;

	return 0;
}

inserte la descripción de la imagen aquí

En el ejemplo de "fideos + pimienta + comino", la impresión del registro es desordenada, porque la impresión de costos de la clase decoradora está anidada, por lo que la impresión del registro es desordenada.

inserte la descripción de la imagen aquí

estructura:

  • Interfaz abstracta decorada (Comida): proporciona métodos de funciones básicas e interfaces de métodos de decoración.
  • Decoradores específicos (fideos): heredan clases abstractas e implementan interfaces de métodos.
  • Clase pública Decorator (Decorator): implementa un método de decoración unificado.
  • Clase de decorador de hormigón: propiedades de decorador personalizadas.

Escenario de uso: en el proceso de desarrollo de software, a veces desea utilizar algunos componentes existentes (objetos definidos) . Es posible que estos componentes solo realicen algunas funciones básicas. Pero su funcionalidad se puede ampliar dinámicamente sin cambiar su arquitectura . Entonces, todos estos pueden implementarse usando el patrón decorador.

Características:

El patrón de diseño del decorador se implementa en forma de composición + herencia.

La clase decoradora y la clase decorada pueden desarrollarse independientemente sin estar acopladas entre sí.

El patrón decorador es una alternativa a la herencia.El patrón decorador puede ampliar dinámicamente la funcionalidad de una clase de implementación.

Supongo que te gusta

Origin blog.csdn.net/weixin_44477424/article/details/131905486
Recomendado
Clasificación