1.前言
"工厂+装饰+策略+观察者"是常见且常用的设计模式之一,但并不是指称"四大模式"的官方术语。
"四大模式"通常是指指令式面向对象编程中的四个基本概念:封装、继承、多态和抽象。这四个概念是面向对象编程的基石。
2.工厂模式
工厂模式(例:工厂方法模式)中,通常存在一个抽象的工厂类和多个具体的工厂子类。每个工厂子类负责创建一种具体的对象,具体的创建逻辑在工厂子类中实现。客户端通过与工厂接口进行交互,并由工厂子类来创建所需的对象。
/* 将工厂也声明成一个基类 */
class TaskBase
{
public:
TaskBase();
virtual ~CalculatorBase();
virtual void exec(unsigned char *data) = 0;
private:
...
};
class TaskA : public TaskBase
{
public:
TaskA();
~TaskA();
virtual void exec(unsigned char *data) override;
private:
...
};
class TaskB : public TaskBase
{
public:
TaskA();
~TaskB();
virtual void exec(unsigned char *data) override;
private:
...
};
int main()
{
TaskBase *task_1 = new TaskA();
TaskBase *task_2 = new TaskB();
TaskBase *current;
int type = 1; // 进行工厂的选择
if(type == 0)
current = task_1;
else
current = task_2;
current->exec();
return 0;
}
这种模式特别适合task任务的选择
3.装饰模式
装饰器模式是一种结构型设计模式,用于动态地给对象添加额外的行为,同时又不修改原始对象的结构。装饰器模式通过将对象包装在一个具有相同接口的装饰器类中,可以在运行时添加、修改或删除对象的功能。
装饰器模式的核心思想是使用继承和组合,通过创建具有相同接口的装饰器类来包装原始对象。装饰器类拥有与原始对象相同的接口,并持有一个指向原始对象的引用。装饰器类可以在执行原始对象的方法前后添加自定义的行为,以扩展原始对象的功能。
#include <iostream>
#include <string>
// 抽象订单接口
class Order
{
public:
virtual void process() = 0;
};
// 具体订单类
class SimpleOrder : public Order
{
public:
void process() override
{
std::cout << "处理简单订单" << std::endl;
}
};
// 抽象装饰器类
class OrderDecorator : public Order
{
protected:
Order* decoratedOrder; // 持有一个指向原始订单的引用
public:
OrderDecorator(Order* order) : decoratedOrder(order) {}
void process() override
{
decoratedOrder->process();
}
};
// 具体装饰器类A
class UrgentOrderDecorator : public OrderDecorator
{
public:
UrgentOrderDecorator(Order* order) : OrderDecorator(order) {}
void process() override
{
OrderDecorator::process();
std::cout << "添加急件处理" << std::endl;
}
};
// 具体装饰器类B
class InternationalOrderDecorator : public OrderDecorator
{
public:
InternationalOrderDecorator(Order* order) : OrderDecorator(order) {}
void process() override
{
OrderDecorator::process();
std::cout << "添加国际订单处理" << std::endl;
}
};
int main()
{
Order* order = new SimpleOrder();
order->process(); // 处理简单订单
Order* urgentOrder = new UrgentOrderDecorator(order);
urgentOrder->process(); // 处理简单订单,并添加急件处理
Order* internationalOrder = new InternationalOrderDecorator(order);
internationalOrder->process(); // 处理简单订单,并添加国际订单处理
Order* urgentInternationalOrder = new UrgentOrderDecorator(new InternationalOrderDecorator(order));
urgentInternationalOrder->process(); // 处理简单订单,并同时添加国际订单和急件处理
delete urgentInternationalOrder;
delete internationalOrder;
delete urgentOrder;
delete order;
return 0;
}
在这个例子中,抽象订单接口Order
定义了订单的处理方法process()
。SimpleOrder
是具体订单类,它实现了订单的处理逻辑。OrderDecorator
是抽象装饰器类,它持有一个指向原始订单的引用,并在订单处理前后添加额外的功能。UrgentOrderDecorator
和InternationalOrderDecorator
是具体装饰器类,分别给订单添加了急件处理和国际订单处理。
客户端代码演示了不同的订单处理情况。通过创建不同的装饰器对象来包装原始订单对象,可以在处理订单时添加额外的功能。每个装饰器类都在执行原始订单的处理方法前后添加了自己特定的行为。
这个例子展示了装饰器模式的灵活性,可以在不修改订单类的情况下,动态地添加、修改或删除订单的功能。它允许通过装饰器组合来创建不同的订单处理方式。
处理简单订单
处理简单订单
添加急件处理
处理简单订单
添加国际订单处理
处理简单订单
添加国际订单处理
添加急件处理
处理简单订单
添加急件处理
添加国际订单处理
4.策略模式
C++策略模式(Strategy Pattern)是一种行为设计模式,它允许在运行时动态地选择算法或行为。该模式将算法封装在独立的策略类中,使得它们可以相互替换,而不影响客户端代码。这种灵活性使得我们可以根据不同的情境选择不同的算法,提高代码的复用性和可维护性。
#include <iostream>
// 定义抽象策略接口
class SendStrategy
{
public:
virtual void sendData(const std::string& data) const = 0;
};
// 定义具体策略类:UART发送
class UartStrategy : public SendStrategy
{
public:
void sendData(const std::string& data) const override
{
std::cout << "UART发送数据:" << data << std::endl;
}
};
// 定义具体策略类:TCP发送
class TcpStrategy : public SendStrategy
{
public:
void sendData(const std::string& data) const override
{
std::cout << "TCP发送数据:" << data << std::endl;
}
};
// 定义具体策略类:UDP发送
class UdpStrategy : public SendStrategy
{
public:
void sendData(const std::string& data) const override
{
std::cout << "UDP发送数据:" << data << std::endl;
}
};
// 定义环境类
class DataSender {
private:
SendStrategy* strategy;
public:
explicit DataSender(SendStrategy* strategy) : strategy(strategy) {}
void setStrategy(SendStrategy* strategy)
{
this->strategy = strategy;
}
void sendData(const std::string& data)
{
if (strategy)
{
strategy->sendData(data);
}
}
};
int main()
{
// 创建具体策略对象
SendStrategy* uart = new UartStrategy();
SendStrategy* tcp = new TcpStrategy();
SendStrategy* udp = new UdpStrategy();
// 创建环境对象并设置初始策略
DataSender sender(uart);
// 发送数据
sender.sendData("Hello, World!");
// 切换为TCP发送
sender.setStrategy(tcp);
sender.sendData("Hello, TCP!");
// 切换为UDP发送
sender.setStrategy(udp);
sender.sendData("Hello, UDP!");
// 释放资源
delete uart;
delete tcp;
delete udp;
return 0;
}
我们首先定义了一个抽象策略接口SendStrategy
,然后实现了三个具体的策略类UartStrategy
、TcpStrategy
和UdpStrategy
,分别用于UART、TCP和UDP发送。
接着,我们定义了环境类DataSender
,它维护了一个指向具体策略对象的引用,并提供了一个公共接口sendData()
以供客户端代码调用。
在主函数中,我们创建了具体策略对象,并将初始策略设置为UART发送。然后,我们使用环境对象的sendData()
方法来发送数据。
接着,我们切换策略为TCP发送和UDP发送,并分别调用环境对象的sendData()
方法。
5.观察者模式
C++观察者模式(Observer Pattern)是一种行为设计模式,它使用一对多的依赖关系,当一个对象(主题)的状态发生变化时,自动通知并更新其他依赖于它的对象(观察者)。观察者模式提供了一种松耦合的方式,使得主题和观察者可以独立变化,而不需要相互了解具体的实现细节。
观察者模式的主要角色包括:
- Subject(主题):它通常是一个抽象类或接口,定义了增加、删除和通知观察者的方法。
- ConcreteSubject(具体主题):它是主题的具体实现,存储了具体观察者对象,并在状态发生变化时通知观察者。
- Observer(观察者):它定义了观察者接收通知并更新自己的方法。
- ConcreteObserver(具体观察者):它是观察者的具体实现,实现了接收通知和更新自身的方法。
#include <iostream>
#include <vector>
// 定义观察者接口
class Observer {
public:
virtual void update(const std::string& news) = 0;
};
// 定义具体观察者类
class Subscriber : public Observer {
private:
std::string name;
public:
explicit Subscriber(const std::string& name) : name(name) {}
void update(const std::string& news) override {
std::cout << name << " 收到新闻:" << news << std::endl;
}
};
// 定义主题类
class NewsChannel {
private:
std::vector<Observer*> observers;
std::string latestNews;
public:
void addObserver(Observer* observer) {
observers.push_back(observer);
}
void removeObserver(Observer* observer) {
// 在实际应用中可能需要实现删除观察者的逻辑
}
void notifyObservers() {
for (auto observer : observers) {
observer->update(latestNews);
}
}
void setNews(const std::string& news) {
latestNews = news;
notifyObservers();
}
};
int main() {
// 创建主题类(新闻频道)
NewsChannel newsChannel;
// 创建观察者类(订阅者)
Observer* subscriber1 = new Subscriber("订阅者1");
Observer* subscriber2 = new Subscriber("订阅者2");
// 添加观察者到主题中
newsChannel.addObserver(subscriber1);
newsChannel.addObserver(subscriber2);
// 发布新闻
newsChannel.setNews("今天天气晴朗,适合出游!");
// 释放资源
delete subscriber1;
delete subscriber2;
return 0;
}
拓展:委托机制下的观察者模式
#include <iostream>
#include <vector>
#include <thread>
#include <mutex>
// 定义一个委托类
template<typename... Args>
class Delegate {
public:
using FunctionPtr = std::function<void(Args...)>;
void Add(FunctionPtr function) {
std::lock_guard<std::mutex> lock(mutex);
delegates.push_back(function);
}
void Remove(FunctionPtr function) {
std::lock_guard<std::mutex> lock(mutex);
delegates.erase(std::remove(delegates.begin(), delegates.end(), function), delegates.end());
}
void Invoke(Args... args) {
std::lock_guard<std::mutex> lock(mutex);
for (auto delegate : delegates) {
delegate(args...);
}
}
private:
std::vector<FunctionPtr> delegates;
std::mutex mutex;
};
// 定义观察者基类
class Observer {
public:
virtual void Notify() = 0;
};
// 定义具体观察者类
class ConcreteObserver : public Observer {
public:
ConcreteObserver(Delegate<void>& delegate) : delegate(delegate) {}
void Notify() override {
// 当前线程接收到通知后的处理代码
std::cout << "ConcreteObserver received notification in thread: " << std::this_thread::get_id() << std::endl;
}
private:
Delegate<void>& delegate;
};
// 定义主题类
class Subject {
public:
void AddObserver(Observer* observer) {
std::lock_guard<std::mutex> lock(mutex);
observers.push_back(observer);
}
void RemoveObserver(Observer* observer) {
std::lock_guard<std::mutex> lock(mutex);
observers.erase(std::remove(observers.begin(), observers.end(), observer), observers.end());
}
void NotifyObservers() {
std::lock_guard<std::mutex> lock(mutex);
for (auto observer : observers) {
observer->Notify();
}
}
private:
std::vector<Observer*> observers;
std::mutex mutex;
};
// 工作线程函数
void WorkerThread(Subject& subject) {
// 在工作线程中执行一些任务...
// 完成后通知观察者
std::this_thread::sleep_for(std::chrono::seconds(2)); // 模拟工作
subject.NotifyObservers();
}
int main() {
// 创建委托对象
Delegate<void> delegate;
// 创建观察者对象
ConcreteObserver observer(delegate);
// 创建主题对象
Subject subject;
// 将观察者注册到主题中
subject.AddObserver(&observer);
// 创建工作线程并传递主题对象
std::thread workerThread(WorkerThread, std::ref(subject));
// 主线程中执行其他任务
std::cout << "Main thread doing some work..." << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
// 等待工作线程结束
workerThread.join();
return 0;
}