文章目录
一、创建型模式
1. 单例模式
C++八股 ------ 单例模式_c++ 单例模式-CSDN博客
2. 工厂模式
参考:【设计模式】工厂模式详解-----简单工厂模式、工厂方法模式、抽象工厂模式-CSDN博客
什么是工厂模式
工厂模式是一种创建型设计模式,它提供了一种创建对象的最佳方式,而无需暴露对象创建的逻辑细节。
工厂模式的三种类型
- 简单工厂模式:一个工厂类根据传入的参数决定创建哪种产品类的实例
- 工厂方法模式:定义一个创建对象的接口,但让子类决定实例化哪个类
- 抽象工厂模式:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类
工厂模式的优点
- 封装创建逻辑:将对象的创建与使用分离
- 代码解耦:客户端代码不需要知道具体产品类的类名
- 易于扩展:添加新产品时,只需扩展工厂类,符合开闭原则
- 统一管理:可以对对象的创建进行统一的管理和控制
适用场景
- 当一个类不知道它所必须创建的对象的类时
- 当一个类希望由其子类来指定它所创建的对象时
- 当类将创建对象的职责委托给多个帮助子类中的某一个,并且你希望将哪一个帮助子类是代理者这一信息局部化时
简单工程模式示例
cpp
#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;
}
工厂方法模式
cpp
#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;
}
抽象工程模式
cpp
#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
接口,我们需要动态地为其添加压缩和加密的功能。
cpp
#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;
}
输出:
text
Writing "Hello World" to a file.
---------------
Writing "Compressed(Hello World)" to a file.
---------------
Writing "Compressed(Encrypted(Hello World))" to a file.
2. 代理模式
核心思想:为另一个对象提供一个替身或占位符以控制对这个对象的访问。
常见代理类型:
- 远程代理:为一个对象在不同的地址空间提供局部代表(例如,RPC调用)。
- 虚拟代理:根据需要创建开销很大的对象(如图片懒加载)。
- 保护代理:控制对原始对象的访问权限。
- 智能引用代理:在对象被访问时执行附加操作(如引用计数、日志记录)。
C++ 样例 :
虚拟代理:延迟加载大图片。
cpp
#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;
}
输出:
text
Image object created. Image not loaded yet.
Loading image: test_10MB_photo.jpg (This is an expensive operation!)
Displaying image: test_10MB_photo.jpg
Second display call:
Displaying image: test_10MB_photo.jpg
三、行为型模式
1. 观察者模式
核心思想:定义对象间的一种一对多的依赖关系,当一个对象(主题)的状态发生改变时,所有依赖于它的对象(观察者)都得到通知并被自动更新。又称"发布-订阅"模式。
比喻:报纸订阅。出版社(主题)负责出版报纸。你(观察者)向出版社订阅后,一旦有新报纸出版,出版社就会自动送到你家。你也可以随时取消订阅。
C++ 样例 :
使用现代C++的特性实现。
cpp
#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;
}
输出:
text
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++ 样例:
cpp
#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;
}
输出:
text
Total: $30
Paid $30 using PayPal (john.doe@example.com)
Checkout successful! Enjoy your items.
注:以上内容大部分由DeepSeek生成