23种设计模式详解

一、概述

(1)创建型设计模式:只关注对象的创建机制,提供一种更灵活、更复杂的对象创建方式,而不是直接实例化对象。

1. 单例模式:确保类只有一个实例,并提供全局访问点。

2. 工厂方法模式:定义一个出创建对象的接口,但将对象的实际创建延迟到子类。

3. 抽象工厂模式:提供一个创建相关对象家族的接口,而无需指定具体类。

4. 建造者模式:将一个复杂对象的构建过程分解为多个步骤,以便更灵活的创建对象。

5. 原型模式:通过复制现有对象来创建新对象,而不是从头开始创建。

(2)结构性设计模式:关注如何组合类和对象以形成更大的结构,以解决系统中对象之间的关系。

1. 适配器模式:允许将一个接口转换为另一个客户端期望的接口。

2. 装饰者模式:动态地为对象添加新的功能,而无需修改其源代码。

3. 代理模式:提供一个代理对象以控制对其他对象的访问。

4. 组合模式:允许客户端以统一的方式处理单个对象和对象组合。

5. 桥接模式:将抽象部分与其实现分离,以便他们可以独立变化。

6. 外观设计模式:提供一个高级别的接口,将多个底层接口组合成一个更简单的接口,以供客户端使用。有助于隔离客户端代码和复杂子系统之间的耦合关系。

7. 享元模式:用于减少创建对象的数量,以减少内存占用和提高性能。

(3)行为型模式:关注对象之间的通信和职责分配,以帮助在系统中实现更松散耦合的对象之间的通信。

1. 策略模式:定义一系列算法,将他们封装成对象,并使其可以互相使用,以便根据需要动态选择算法。

2. 模板方法模式:定义一个算法的骨架,而将一些步骤的具体步骤延迟到子类中。允许在不改变算法结构的情况下,通过子类重写或扩展某些步骤来指定算法的行为。

3. 观察者模式:定义一种一对多的依赖关系,使得当一个对象状态发生变化时,所有依赖于它的对象都得到通知并自动更新。

4. 迭代器模式:

5. 责任链模式:将请求的发送者和接收者解耦,以便多个对象都有机会处理请求,将请求沿链传递,直到有一个对象处理它为止。

6. 命令模式:将请求封装成对象,以便可以参数化客户端对象,排队请求和记录日志,以及支持可撤销操作。

7. 备忘录模式:

8. 状态模式:允许对象在其内部状态发生变化时改变其行为。

9. 访问者模式:

10. 中介者模式:

11. 解释器模式:

二、单例模式

        可以保证一个类只有一个实例;分为两种:饿汉式、懒汉式。

        懒汉式:实例在第一次被请求时创建。有线程安全问题。

        饿汉式:实例在类加载时就被创建,不管是否需要使用它,没有线程安全问题。

//有线程安全问题的懒汉式
class Singleton {
private:
	static Singleton* instance;

	Singleton() {}  // 私有构造函数,禁止外部实例化

public:
	static Singleton* getInstance() {
		if (instance == nullptr) {
			instance = new Singleton();
		}
		return instance;
	}
};

//无线程安全问题的懒汉式:局部静态变量只有在第一次加载时才会初始化
class Singleton {
private:
	Singleton() {}  // 私有构造函数,禁止外部实例化

public:
	static Singleton* getInstance() {
	    static Singleton* instance = new Singleton();
		return instance;
	}
};

//加双检锁解决线程安全的懒汉式
class Singleton {
private:
	static Singleton* instance;
	static std::mutex mtx;  // 用于线程安全的锁

	Singleton() {}  // 私有构造函数,禁止外部实例化

public:
	static Singleton* getInstance() {
		// 第一次检查,如果实例已经存在,直接返回
		if (instance == nullptr) {
			std::lock_guard<std::mutex> lock(mtx);  // 加锁
			// 第二次检查,防止在等待锁期间其他线程已经创建实例
			if (instance == nullptr) {
				instance = new Singleton();  // 创建实例
			}
		}
		return instance;
	}
};
// 静态成员初始化
Singleton* Singleton::instance = nullptr;
std::mutex Singleton::mtx;


//饿汉式
class Singleton {
private:
	static Singleton* instance;

	Singleton() {}  // 私有构造函数,禁止外部实例化

public:
	static Singleton* getInstance() {
		return instance;
	}
};
Singleton* Singleton::instance = new Singleton;

         懒汉式需要考虑多线程环境下的线程安全问题。可以使用加锁方式来确保线程安全,C++11后可以用局部静态变量来解决线程安全问题。饿汉式的优点是实现简单和线程安全,但可能存在内存浪费。

三、简单工厂模式

         客户端只需要通过工厂类来创建所需的对象,而不需要直接实例化具体的对象,具体操作由工厂类内部实现。

// 产品类 - 图形
class Shape {
public:
	virtual void draw() = 0;
};

// 具体产品类 - 圆形
class Circle : public Shape {
public:
	void draw() override {
		std::cout << "绘制圆形" << std::endl;
	}
};

// 具体产品类 - 矩形
class Rectangle : public Shape {
public:
	void draw() override {
		std::cout << "绘制矩形" << std::endl;
	}
};

// 工厂类
class ShapeFactory {
public:
	// 根据类型创建图形对象
	static Shape* createShape(std::string type) {
		if (type == "Circle") {
			return new Circle();
		}
		else if (type == "Rectangle") {
			return new Rectangle();
		}
		else {
			return nullptr; // 可以根据需要添加其他图形类型的创建逻辑
		}
	}
};

//使用
int main() {
    Shape* shape1 = ShapeFactory::createShape("Circle");
    Shape* shape2 = ShapeFactory::createShape("Rectangle");
    shape1->draw();//绘制圆形
    shape2->draw();//绘制矩形
}

        优点:封装了对象的创建过程,客户端代码与具体类解耦,降低了代码的维护复杂度。

        缺点:当需要添加新的产品类型时,需要修改工厂类的代码,违反了开闭原则(对扩展开放,对修改关闭)。

四、抽象工厂

         创建一组相关的产品,而不是单个产品。

#include <iostream>

// 抽象产品接口
class Button {
public:
	virtual void render() = 0;
};

// 具体产品类A
class WindowsButton : public Button {
public:
	void render() override {
		std::cout << "Rendering a Windows button." << std::endl;
	}
};

// 具体产品类B
class MacButton : public Button {
public:
	void render() override {
		std::cout << "Rendering a Mac button." << std::endl;
	}
};

// 抽象工厂接口
class GUIFactory {
public:
	virtual Button* createButton() = 0;
};

// 具体工厂类A
class WindowsFactory : public GUIFactory {
public:
	Button* createButton() override {
		return new WindowsButton();
	}
};

// 具体工厂类B
class MacFactory : public GUIFactory {
public:
	Button* createButton() override {
		return new MacButton();
	}
};

int main() {
	// 创建一个Windows风格的工厂
	GUIFactory* windowsFactory = new WindowsFactory();
	// 创建一个Windows风格的按钮
	Button* windowsButton = windowsFactory->createButton();
	// 渲染按钮
	windowsButton->render();  // Output: Rendering a Windows button.

	// 创建一个Mac风格的工厂
	GUIFactory* macFactory = new MacFactory();
	// 创建一个Mac风格的按钮
	Button* macButton = macFactory->createButton();
	// 渲染按钮
	macButton->render();  // Output: Rendering a Mac button.

	delete windowsFactory;
	delete windowsButton;
	delete macFactory;
	delete macButton;

	return 0;
}

        可以实现一系列产品的一致性和互换性,同时也符合了开闭原则,是的系统更加灵活和可扩展。 

五、建造者模式

        将对象的构建过程与其表示分离,逐步构建复杂的对象。

#include <iostream>
#include <string>

// 产品类
class Pizza {
public:
	void setDough(const std::string& dough) {
		m_dough = dough;
	}

	void setSauce(const std::string& sauce) {
		m_sauce = sauce;
	}

	void setTopping(const std::string& topping) {
		m_topping = topping;
	}

	void showPizza() const {
		std::cout << "Pizza with " << m_dough << " dough, " << m_sauce << " sauce, and " << m_topping << " topping." << std::endl;
	}

private:
	std::string m_dough;
	std::string m_sauce;
	std::string m_topping;
};

// 抽象建造者类
class PizzaBuilder {
public:
	virtual ~PizzaBuilder() {}

	virtual void buildDough() = 0;
	virtual void buildSauce() = 0;
	virtual void buildTopping() = 0;
	virtual Pizza* getPizza() = 0;
};

// 具体建造者类A
class HawaiianPizzaBuilder : public PizzaBuilder {
public:
	void buildDough() override {
		m_pizza->setDough("cross");
	}

	void buildSauce() override {
		m_pizza->setSauce("mild");
	}

	void buildTopping() override {
		m_pizza->setTopping("ham and pineapple");
	}

	Pizza* getPizza() override {
		return m_pizza;
	}

private:
	Pizza* m_pizza = new Pizza();
};

// 具体建造者类B
class SpicyPizzaBuilder : public PizzaBuilder {
public:
	void buildDough() override {
		m_pizza->setDough("pan baked");
	}

	void buildSauce() override {
		m_pizza->setSauce("hot");
	}

	void buildTopping() override {
		m_pizza->setTopping("pepperoni and jalapeno");
	}

	Pizza* getPizza() override {
		return m_pizza;
	}

private:
	Pizza* m_pizza = new Pizza();
};

// 指导者类
class PizzaDirector {
public:
	void setPizzaBuilder(PizzaBuilder* builder) {
		m_builder = builder;
	}

	void constructPizza() {
		m_builder->buildDough();
		m_builder->buildSauce();
		m_builder->buildTopping();
	}

private:
	PizzaBuilder* m_builder;
};

int main() {
	PizzaDirector director;

	HawaiianPizzaBuilder hawaiianBuilder;
	director.setPizzaBuilder(&hawaiianBuilder);
	director.constructPizza();
	Pizza* hawaiianPizza = hawaiianBuilder.getPizza();
	hawaiianPizza->showPizza();

	SpicyPizzaBuilder spicyBuilder;
	director.setPizzaBuilder(&spicyBuilder);
	director.constructPizza();
	Pizza* spicyPizza = spicyBuilder.getPizza();
	spicyPizza->showPizza();
	delete hawaiianPizza;
	delete spicyPizza;

	return 0;
}

        优点:将对象的构建过程和表示分离,使得构建过程更加灵活,同时可以避免构造函数的参数过多的问题。

六、原型模式

        通过复制已有的对象来创建新的对象,而无需重新构造对象。

#include <iostream>
#include <string>

// 图形基类
class Shape {
public:
	virtual ~Shape() {}
	virtual void draw() = 0;
	virtual Shape* clone() = 0;
};

// 圆形类
class Circle : public Shape {
private:
	std::string color;
	int radius;

public:
	Circle(std::string color, int radius) : color(color), radius(radius) {}

	void draw() override {
		std::cout << "Drawing a circle with color " << color << " and radius " << radius << std::endl;
	}

	Shape* clone() override {
		return new Circle(*this);
	}
};

int main() {
	// 创建一个原型对象
	Shape* circlePrototype = new Circle("red", 5);

	// 克隆原型对象来创建新对象
	Shape* circle1 = circlePrototype->clone();
	Shape* circle2 = circlePrototype->clone();

	// 绘制图形
	circle1->draw();  // Output: Drawing a circle with color red and radius 5
	circle2->draw();  // Output: Drawing a circle with color red and radius 5

	delete circlePrototype;
	delete circle1;
	delete circle2;

	return 0;
}

七、适配器模式

        通过适配器可以将一个类的接口转换为另一个类的接口,是的两者可以无缝协同工作。

        有三个角色:目标接口、适配器、被适配者

#include <iostream>

// 目标接口
class Target {
public:
	virtual void request() = 0;
};

// 被适配者类
class Adaptee {
public:
	void specificRequest() {
		std::cout << "被适配者的特殊请求" << std::endl;
	}
};

// 类适配器
class Adapter : public Target, private Adaptee {
public:
	void request() override {
		specificRequest();
	}
};

int main() {
	Target* adapter = new Adapter();
	adapter->request();

	delete adapter;

	return 0;
}

八、装饰者模式

                将对象包装在一个装饰者类中,然后逐层地添加装饰者,从而实现对对象的透明扩展。

#include <iostream>

// 抽象构件
class Component {
public:
	virtual void operation() = 0;
};

// 具体构件
class ConcreteComponent : public Component {
public:
	void operation() override {
		std::cout << "执行具体构件的操作" << std::endl;
	}
};

// 抽象装饰者
class Decorator : public Component {
protected:
	Component* component;

public:
	Decorator(Component* component) : component(component) {}

	void operation() override {
		if (component != nullptr) {
			component->operation();
		}
	}
};

// 具体装饰者A
class ConcreteDecoratorA : public Decorator {
public:
	ConcreteDecoratorA(Component* component) : Decorator(component) {}

	void operation() override {
		addedBehavior();
		Decorator::operation();
	}

	void addedBehavior() {
		std::cout << "具体装饰者A的附加操作" << std::endl;
	}
};

// 具体装饰者B
class ConcreteDecoratorB : public Decorator {
public:
	ConcreteDecoratorB(Component* component) : Decorator(component) {}

	void operation() override {
		addedBehavior();
		Decorator::operation();
	}

	void addedBehavior() {
		std::cout << "具体装饰者B的附加操作" << std::endl;
	}
};

int main() {
	Component* component = new ConcreteComponent();

	Component* decoratorA = new ConcreteDecoratorA(component);
	decoratorA->operation();

	Component* decoratorB = new ConcreteDecoratorB(decoratorA);
	decoratorB->operation();

	delete decoratorB;
	delete decoratorA;
	delete component;

	return 0;
}

九、代理模式

        通过引入一个代理对象来替代原始对象,从而可以在不改变原始对象的情况下增加额外的功能或控制访问。

        有三个角色:抽象主题、真实主题、代理

#include <iostream>

// 抽象主题
class Subject {
public:
	virtual void request() = 0;
};

// 真实主题
class RealSubject : public Subject {
public:
	void request() override {
		std::cout << "真实主题的请求" << std::endl;
	}
};

// 代理
class Proxy : public Subject {
private:
	RealSubject* realSubject;

public:
	Proxy() {
		realSubject = new RealSubject();
	}

	~Proxy() {
		delete realSubject;
	}

	void request() override {
		// 在调用真实主题之前可以添加额外的逻辑
		std::cout << "代理的请求" << std::endl;

		// 委托给真实主题处理
		realSubject->request();
	}
};

int main() {
	Subject* proxy = new Proxy();
	proxy->request();

	delete proxy;

	return 0;
}

十、组合模式

        有两种基本类型对象:叶子对象和组合对象。叶子对象表示树中的最细粒度的对象,没有子对象;组合对象是由一个或多个叶子对象或其他组合对象组成的对象,可以拥有子对象。

#include <iostream>
#include <vector>

// 抽象组件类
class Component {
public:
	virtual void operation() = 0;
};

// 叶子组件类
class Leaf : public Component {
public:
	void operation() override {
		std::cout << "叶子组件的操作" << std::endl;
	}
};

// 组合组件类
class Composite : public Component {
private:
	std::vector<Component*> components;

public:
	void addComponent(Component* component) {
		components.push_back(component);
	}

	void operation() override {
		std::cout << "组合组件的操作" << std::endl;
		for (Component* component : components) {
			component->operation();
		}
	}
};

int main() {
	Component* leaf = new Leaf();
	Component* composite = new Composite();
	composite->addComponent(leaf);

	composite->operation();

	delete composite;
	delete leaf;

	return 0;
}

十一、桥接模式

十二、外观设计模式

        允许客户端通过与外观对象交互,而不必直接与子系统的复杂性相互作用,降低客户端代码的复杂性和依赖性。

// 外观类 - 多媒体播放器
class MultimediaPlayer {
private:
	AudioPlayer audioPlayer;
	VideoPlayer videoPlayer;
	SubtitlePlayer subtitlePlayer;

public:
	MultimediaPlayer() {
		// 初始化子系统
	}

	// 提供一个播放多媒体文件的简化接口
	void playMedia(const std::string& mediaFilePath) {
		audioPlayer.playAudio(mediaFilePath);
		videoPlayer.playVideo(mediaFilePath);
		subtitlePlayer.displaySubtitles(mediaFilePath);
	}
};

// 子系统类 - 音频播放器
class AudioPlayer {
public:
	void playAudio(const std::string& filePath) {
		std::cout << "播放音频:" << filePath << std::endl;
		// 实际音频播放逻辑
	}
};

// 子系统类 - 视频播放器
class VideoPlayer {
public:
	void playVideo(const std::string& filePath) {
		std::cout << "播放视频:" << filePath << std::endl;
		// 实际视频播放逻辑
	}
};

// 子系统类 - 字幕显示器
class SubtitlePlayer {
public:
	void displaySubtitles(const std::string& filePath) {
		std::cout << "显示字幕:" << filePath << std::endl;
		// 实际字幕显示逻辑
	}
};

十三、享元模式

        通过共享对象来最小化内存使用和提高性能。

#include <iostream>
#include <vector>
#include <unordered_map>

// 抽象享元类
class Flyweight {
public:
	virtual void operation(int extrinsicState) = 0;
};

// 具体享元类
class ConcreteFlyweight : public Flyweight {
public:
	void operation(int extrinsicState) override {
		std::cout << "具体享元对象,外部状态为:" << extrinsicState << std::endl;
	}
};

// 享元工厂类
class FlyweightFactory {
private:
	std::unordered_map<int, Flyweight*> flyweights;

public:
	Flyweight* getFlyweight(int key) {
		if (flyweights.find(key) == flyweights.end()) {
			flyweights[key] = new ConcreteFlyweight();
		}
		return flyweights[key];
	}
};

int main() {
	FlyweightFactory factory;

	Flyweight* flyweight = factory.getFlyweight(1);
	flyweight->operation(100);

	flyweight = factory.getFlyweight(2);
	flyweight->operation(200);

	return 0;
}

十四、策略模式

十五、模板方法模式

十六、观察者模式

十七、迭代器模式

十八、责任链模式

十九、命令模式

二十、备忘录模式

二十一、状态模式

二十二、访问者模式

二十三、中介者模式

二十四、解释器模式

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值