文章目录
- 一、创建型模式
- 1. 单例模式
- 2. 工厂模式
- 二、结构型模式
- 1. 装饰器模式
- 2. 代理模式
- 三、行为型模式
- 1. 观察者模式
- 2. 策略模式
一、创建型模式
1. 单例模式
C++八股 —— 单例模式_c++ 单例模式-CSDN博客
2. 工厂模式
参考:【设计模式】工厂模式详解-----简单工厂模式、工厂方法模式、抽象工厂模式-CSDN博客
什么是工厂模式
工厂模式是一种创建型设计模式,它提供了一种创建对象的最佳方式,而无需暴露对象创建的逻辑细节。
工厂模式的三种类型
- 简单工厂模式:一个工厂类根据传入的参数决定创建哪种产品类的实例
- 工厂方法模式:定义一个创建对象的接口,但让子类决定实例化哪个类
- 抽象工厂模式:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类
工厂模式的优点
- 封装创建逻辑:将对象的创建与使用分离
- 代码解耦:客户端代码不需要知道具体产品类的类名
- 易于扩展:添加新产品时,只需扩展工厂类,符合开闭原则
- 统一管理:可以对对象的创建进行统一的管理和控制
适用场景
- 当一个类不知道它所必须创建的对象的类时
- 当一个类希望由其子类来指定它所创建的对象时
- 当类将创建对象的职责委托给多个帮助子类中的某一个,并且你希望将哪一个帮助子类是代理者这一信息局部化时
简单工程模式示例
#include <iostream>
#include <string>
#include <memory>// 产品接口
class Shape {
public:virtual void draw() = 0;virtual ~Shape() {}
};// 具体产品类
class Circle : public Shape {
public:void draw() override {std::cout << "Drawing a Circle" << std::endl;}
};class Rectangle : public Shape {
public:void draw() override {std::cout << "Drawing a Rectangle" << std::endl;}
};class Triangle : public Shape {
public:void draw() override {std::cout << "Drawing a Triangle" << std::endl;}
};// 简单工厂
class ShapeFactory {
public:static std::unique_ptr<Shape> createShape(const std::string& shapeType) {if (shapeType == "CIRCLE") {return std::make_unique<Circle>();} else if (shapeType == "RECTANGLE") {return std::make_unique<Rectangle>();} else if (shapeType == "TRIANGLE") {return std::make_unique<Triangle>();}return nullptr;}
};int main() {// 使用工厂创建对象auto circle = ShapeFactory::createShape("CIRCLE");auto rectangle = ShapeFactory::createShape("RECTANGLE");auto triangle = ShapeFactory::createShape("TRIANGLE");circle->draw();rectangle->draw();triangle->draw();return 0;
}
工厂方法模式
#include <iostream>
#include <memory>// 产品接口
class Button {
public:virtual void render() = 0;virtual void onClick() = 0;virtual ~Button() {}
};// 具体产品
class WindowsButton : public Button {
public:void render() override {std::cout << "Rendering a Windows button" << std::endl;}void onClick() override {std::cout << "Windows button clicked" << std::endl;}
};class WebButton : public Button {
public:void render() override {std::cout << "Rendering a Web button" << std::endl;}void onClick() override {std::cout << "Web button clicked" << std::endl;}
};// 创建者类
class Dialog {
public:virtual std::unique_ptr<Button> createButton() = 0;void render() {auto button = createButton();button->render();button->onClick();}virtual ~Dialog() {}
};// 具体创建者
class WindowsDialog : public Dialog {
public:std::unique_ptr<Button> createButton() override {return std::make_unique<WindowsButton>();}
};class WebDialog : public Dialog {
public:std::unique_ptr<Button> createButton() override {return std::make_unique<WebButton>();}
};int main() {std::unique_ptr<Dialog> dialog;// 根据配置或环境选择创建者std::string config = "Windows"; // 可以改为 "Web" 来测试if (config == "Windows") {dialog = std::make_unique<WindowsDialog>();} else if (config == "Web") {dialog = std::make_unique<WebDialog>();}if (dialog) {dialog->render();}return 0;
}
抽象工程模式
#include <iostream>
#include <memory>// 抽象产品A
class Checkbox {
public:virtual void paint() = 0;virtual ~Checkbox() {}
};// 具体产品A1
class WindowsCheckbox : public Checkbox {
public:void paint() override {std::cout << "Rendering a Windows checkbox" << std::endl;}
};// 具体产品A2
class WebCheckbox : public Checkbox {
public:void paint() override {std::cout << "Rendering a Web checkbox" << std::endl;}
};// 抽象产品B
class Button {
public:virtual void paint() = 0;virtual ~Button() {}
};// 具体产品B1
class WindowsButton : public Button {
public:void paint() override {std::cout << "Rendering a Windows button" << std::endl;}
};// 具体产品B2
class WebButton : public Button {
public:void paint() override {std::cout << "Rendering a Web button" << std::endl;}
};// 抽象工厂
class GUIFactory {
public:virtual std::unique_ptr<Button> createButton() = 0;virtual std::unique_ptr<Checkbox> createCheckbox() = 0;virtual ~GUIFactory() {}
};// 具体工厂1
class WindowsFactory : public GUIFactory {
public:std::unique_ptr<Button> createButton() override {return std::make_unique<WindowsButton>();}std::unique_ptr<Checkbox> createCheckbox() override {return std::make_unique<WindowsCheckbox>();}
};// 具体工厂2
class WebFactory : public GUIFactory {
public:std::unique_ptr<Button> createButton() override {return std::make_unique<WebButton>();}std::unique_ptr<Checkbox> createCheckbox() override {return std::make_unique<WebCheckbox>();}
};// 客户端代码
class Application {
private:std::unique_ptr<GUIFactory> factory;std::unique_ptr<Button> button;std::unique_ptr<Checkbox> checkbox;public:Application(std::unique_ptr<GUIFactory> f) : factory(std::move(f)) {}void createUI() {button = factory->createButton();checkbox = factory->createCheckbox();}void paint() {if (button) button->paint();if (checkbox) checkbox->paint();}
};int main() {std::string config = "Windows"; // 可以改为 "Web" 来测试std::unique_ptr<GUIFactory> factory;if (config == "Windows") {factory = std::make_unique<WindowsFactory>();} else if (config == "Web") {factory = std::make_unique<WebFactory>();}if (factory) {auto app = Application(std::move(factory));app.createUI();app.paint();}return 0;
}
二、结构型模式
1. 装饰器模式
核心思想:动态地给一个对象添加一些额外的职责,而无需通过子类继承。它通过创建一个包装对象(即装饰器)来包裹真实对象,提供了比继承更有弹性的替代方案。
比喻:就像给一个礼物打包。你可以先装盒子,再系丝带,最后贴卡片。每个步骤都是在原有礼物的基础上“装饰”新的功能,而不是改变礼物本身。
优点:
- 无需创建大量子类即可扩展功能。
- 可以在运行时动态地添加或撤销功能。
- 符合“开闭原则”(对扩展开放,对修改关闭)。
C++ 样例:
我们有一个简单的Stream
接口,我们需要动态地为其添加压缩和加密的功能。
#include <iostream>
#include <string>// 组件接口
class Stream {
public:virtual void write(const std::string& data) = 0;virtual ~Stream() {}
};// 具体组件
class FileStream : public Stream {
public:void write(const std::string& data) override {std::cout << "Writing \"" << data << "\" to a file." << std::endl;}
};// 装饰器基类
class StreamDecorator : public Stream {
protected:Stream* m_stream; // 持有一个组件对象的引用
public:StreamDecorator(Stream* stream) : m_stream(stream) {}virtual ~StreamDecorator() { delete m_stream; }
};// 具体装饰器 - 压缩
class CompressedStream : public StreamDecorator {
public:CompressedStream(Stream* stream) : StreamDecorator(stream) {}void write(const std::string& data) override {std::string compressedData = "Compressed(" + data + ")";m_stream->write(compressedData); // 调用被装饰对象的方法}
};// 具体装饰器 - 加密
class EncryptedStream : public StreamDecorator {
public:EncryptedStream(Stream* stream) : StreamDecorator(stream) {}void write(const std::string& data) override {std::string encryptedData = "Encrypted(" + data + ")";m_stream->write(encryptedData); // 调用被装饰对象的方法}
};int main() {// 1. 简单的文件流Stream* stream1 = new FileStream();stream1->write("Hello World");delete stream1;std::cout << "---------------" << std::endl;// 2. 动态添加功能:压缩的文件流Stream* stream2 = new CompressedStream(new FileStream());stream2->write("Hello World");delete stream2;std::cout << "---------------" << std::endl;// 3. 动态添加更多功能:先加密再压缩的文件流// 装饰顺序很重要!Stream* stream3 = new CompressedStream(new EncryptedStream(new FileStream()));stream3->write("Hello World");delete stream3;return 0;
}
输出:
Writing "Hello World" to a file.
---------------
Writing "Compressed(Hello World)" to a file.
---------------
Writing "Compressed(Encrypted(Hello World))" to a file.
2. 代理模式
核心思想:为另一个对象提供一个替身或占位符以控制对这个对象的访问。
常见代理类型:
- 远程代理:为一个对象在不同的地址空间提供局部代表(例如,RPC调用)。
- 虚拟代理:根据需要创建开销很大的对象(如图片懒加载)。
- 保护代理:控制对原始对象的访问权限。
- 智能引用代理:在对象被访问时执行附加操作(如引用计数、日志记录)。
C++ 样例:
虚拟代理:延迟加载大图片。
#include <iostream>
#include <string>// 抽象主题
class Image {
public:virtual void display() = 0;virtual ~Image() {}
};// 真实主题
class RealImage : public Image {
private:std::string m_filename;void loadFromDisk() {std::cout << "Loading image: " << m_filename << " (This is an expensive operation!)" << std::endl;}
public:RealImage(const std::string& filename) : m_filename(filename) {loadFromDisk();}void display() override {std::cout << "Displaying image: " << m_filename << std::endl;}
};// 代理
class ProxyImage : public Image {
private:std::string m_filename;RealImage* m_realImage; // 代理持有一个对真实对象的引用public:ProxyImage(const std::string& filename) : m_filename(filename), m_realImage(nullptr) {}~ProxyImage() { delete m_realImage; }void display() override {// 只有在需要时才创建真实对象if (m_realImage == nullptr) {m_realImage = new RealImage(m_filename);}// 委托给真实对象执行请求m_realImage->display();}
};int main() {// 创建代理时,真实对象尚未创建,没有昂贵的加载操作Image* image = new ProxyImage("test_10MB_photo.jpg");std::cout << "Image object created. Image not loaded yet." << std::endl;// 第一次调用display,真实对象被创建和加载image->display();std::cout << std::endl;// 后续调用,真实对象已存在,直接使用std::cout << "Second display call:" << std::endl;image->display();delete image;return 0;
}
输出:
Image object created. Image not loaded yet.
Loading image: test_10MB_photo.jpg (This is an expensive operation!)
Displaying image: test_10MB_photo.jpgSecond display call:
Displaying image: test_10MB_photo.jpg
三、行为型模式
1. 观察者模式
核心思想:定义对象间的一种一对多的依赖关系,当一个对象(主题)的状态发生改变时,所有依赖于它的对象(观察者)都得到通知并被自动更新。又称“发布-订阅”模式。
比喻:报纸订阅。出版社(主题)负责出版报纸。你(观察者)向出版社订阅后,一旦有新报纸出版,出版社就会自动送到你家。你也可以随时取消订阅。
C++ 样例:
使用现代C++的特性实现。
#include <iostream>
#include <vector>
#include <memory>
#include <algorithm>// 观察者接口
class Observer {
public:virtual void update(int temperature) = 0;virtual ~Observer() {}
};// 主题(被观察者)
class WeatherStation {
private:int m_temperature;std::vector<Observer*> m_observers; // 存储观察者指针public:void registerObserver(Observer* observer) {m_observers.push_back(observer);}void removeObserver(Observer* observer) {m_observers.erase(std::remove(m_observers.begin(), m_observers.end(), observer),m_observers.end());}void notifyObservers() {for (auto observer : m_observers) {observer->update(m_temperature);}}void setTemperature(int temp) {m_temperature = temp;std::cout << "Temperature updated to: " << temp << std::endl;notifyObservers(); // 状态改变,通知所有观察者}
};// 具体观察者
class Display : public Observer {
public:void update(int temperature) override {std::cout << "[Display] Current temperature is: " << temperature << "°C" << std::endl;}
};class AlertSystem : public Observer {
public:void update(int temperature) override {if (temperature > 30) {std::cout << "[AlertSystem] Warning! Temperature is too high: " << temperature << "°C" << std::endl;}}
};int main() {WeatherStation station;Display display;AlertSystem alert;// 注册观察者station.registerObserver(&display);station.registerObserver(&alert);// 改变主题状态,触发通知station.setTemperature(25);std::cout << "-------------------" << std::endl;station.setTemperature(35);// 移除一个观察者station.removeObserver(&alert);std::cout << "-------------------" << std::endl;std::cout << "After removing alert system:" << std::endl;station.setTemperature(40);return 0;
}
输出:
Temperature updated to: 25
[Display] Current temperature is: 25°C
[AlertSystem] Warning! Temperature is too high: 25°C
-------------------
Temperature updated to: 35
[Display] Current temperature is: 35°C
[AlertSystem] Warning! Temperature is too high: 35°C
-------------------
After removing alert system:
Temperature updated to: 40
[Display] Current temperature is: 40°C
2. 策略模式
核心思想:定义一系列算法,将每个算法封装起来,并且使它们可以互相替换。策略模式让算法的变化独立于使用算法的客户。
比喻:出行方式。去机场是一个目标(Context),你可以选择不同的策略(Strategy):坐公交、打车、坐地铁。你可以根据时间、金钱等因素轻松替换策略,而改变“去机场”这个行为本身。
优点:
- 避免使用多重条件判断语句(if-else/switch-case)。
- 算法可以自由切换和扩展。
- 符合“开闭原则”。
C++ 样例:
#include <iostream>
#include <memory>
#include <vector>// 策略接口
class PaymentStrategy {
public:virtual void pay(int amount) = 0;virtual ~PaymentStrategy() {}
};// 具体策略
class CreditCardPayment : public PaymentStrategy {
private:std::string m_name;std::string m_cardNumber;
public:CreditCardPayment(const std::string& name, const std::string& cardNumber): m_name(name), m_cardNumber(cardNumber) {}void pay(int amount) override {std::cout << "Paid $" << amount << " using Credit Card (" << m_cardNumber << ")" << std::endl;}
};class PayPalPayment : public PaymentStrategy {
private:std::string m_email;
public:PayPalPayment(const std::string& email) : m_email(email) {}void pay(int amount) override {std::cout << "Paid $" << amount << " using PayPal (" << m_email << ")" << std::endl;}
};class CryptoPayment : public PaymentStrategy {
private:std::string m_walletAddress;
public:CryptoPayment(const std::string& address) : m_walletAddress(address) {}void pay(int amount) override {std::cout << "Paid $" << amount << " using Crypto (Address: " << m_walletAddress << ")" << std::endl;}
};// 上下文(Context)
class ShoppingCart {
private:std::vector<std::string> m_items;std::unique_ptr<PaymentStrategy> m_paymentStrategy;public:void addItem(const std::string& item) {m_items.push_back(item);}int calculateTotal() {// 简化计算,假设每件商品10美元return m_items.size() * 10;}void setPaymentStrategy(std::unique_ptr<PaymentStrategy> strategy) {m_paymentStrategy = std::move(strategy);}void checkout() {int amount = calculateTotal();if (m_paymentStrategy) {m_paymentStrategy->pay(amount);std::cout << "Checkout successful! Enjoy your items." << std::endl;} else {std::cout << "Please set a payment method before checkout." << std::endl;}}
};int main() {ShoppingCart cart;cart.addItem("Book");cart.addItem("Laptop");cart.addItem("Mouse");int total = cart.calculateTotal();std::cout << "Total: $" << total << std::endl;// 用户在运行时选择支付策略int choice = 2; // 可以来自用户输入if (choice == 1) {cart.setPaymentStrategy(std::make_unique<CreditCardPayment>("John Doe", "1234-5678-9012-3456"));} else if (choice == 2) {cart.setPaymentStrategy(std::make_unique<PayPalPayment>("john.doe@example.com"));} else if (choice == 3) {cart.setPaymentStrategy(std::make_unique<CryptoPayment>("0xABC123..."));}cart.checkout();return 0;
}
输出:
Total: $30
Paid $30 using PayPal (john.doe@example.com)
Checkout successful! Enjoy your items.
注:以上内容大部分由DeepSeek生成