目录
观察者模式
观察者模式理论:
观察者模式是一种行为设计模式。它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。当主题对象的状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。在 C++ 中,这种模式可以通过抽象类和虚函数来实现。它的主要角色包括主题(Subject)和观察者(Observer)。主题是被观察的对象,它维护了一个观察者列表,并提供添加、删除观察者和通知观察者的方法。观察者是观察主题的对象,它定义了一个更新接口,当主题状态改变时,主题通过调用观察者的更新接口来通知观察者。
作者理解(大白话):
用一个类为基类记为类A,继承自A的子类B,C,然后在另外一个单独的C类中的成员变量就有vector<A*>这里的A*其实可以是B,也可以是C,因为父类指针可以指向子类对象,不管是B还是C,假设类此时A类写了一个虚函数virture update()函数B和C重写update函数,将来C类中的vector<A*>在进行访问容器中每个元素更新的时候(记住元素是B或者C)会调用对应B或者C自己类里写的update函数,代码如下
#include <iostream>
#include <vector>
// 抽象基类 A,观察者
class A {
public:
virtual void update() = 0; // 纯虚函数,使 A 成为抽象类
virtual ~A() {} // 虚析构函数,确保正确释放派生类资源
};
// 子类 B,继承自 A
class B : public A {
public:
void update() override {
std::cout << "B's update function is called." << std::endl;
}
};
// 子类 C,继承自 A
class C : public A {
public:
void update() override {
std::cout << "C's update function is called." << std::endl;
}
};
// 主题类 D
class D {
private:
std::vector<A*> observers;
int state; // 主题的状态
public:
D() : state(0) {}
// 向容器中添加对象
void attach(A* observer) {
observers.push_back(observer);
}
// 从容器中移除对象
void detach(A* observer) {
auto it = std::find(observers.begin(), observers.end(), observer);
if (it!= observers.end()) {
observers.erase(it);
}
}
// 改变主题状态并通知观察者
void setState(int newState) {
state = newState;
notify();
}
// 通知所有观察者
void notify() {
for (A* observer : observers) {
observer->update();
}
}
// 析构函数,释放存储的指针
~D() {
for (A* observer : observers) {
delete observer;
}
}
};
int main() {
D subject;
B* b = new B();
C* c = new C();
subject.attach(b);
subject.attach(c);
subject.setState(1);
return 0;
}
之所以这样设计,是把B和C存放到一个vector中,将来如果想要更多的A的子类,比如K类,那么vector也可以装得下,增加的代码的重复利用(复用),符合开闭原则(在原来代码上增加,而不是删除修改,即增加K类即可,不需要修改C类代码)
具体观察者模式的利用前后例子如下:
假设我们有一个简单的气象站应用程序,它负责获取温度数据,并且有一个显示设备来显示温度。在这个例子中,WeatherStation
类负责管理温度数据,DisplayDevice
类负责显示温度。但是,如果我们想要添加另一个显示设备或者对温度数据的变化有其他操作(比如记录温度变化历史),我们就需要在WeatherStation
类的setTemperature
方法中添加更多的代码来调用这些新的功能。这样会使WeatherStation
类变得越来越复杂,而且不符合开闭原则(对扩展开放,对修改关闭)。
class WeatherStation {
private:
double temperature;
public:
void setTemperature(double temp) {
temperature = temp;
}
double getTemperature() const {
return temperature;
}
};
class DisplayDevice {
public:
void displayTemperature(const WeatherStation& station) {
std::cout << "当前温度: " << station.getTemperature() << "°C" << std::endl;
}
};
int main() {
WeatherStation station;
DisplayDevice device;
station.setTemperature(25.0);
device.displayTemperature(station);
return 0;
}
使用观察者模式之后:
// 抽象观察者类
class Observer {
public:
virtual void update(double temperature) = 0;
};
// 主题类(气象站)
class WeatherStation {
private:
double temperature;
std::vector<Observer*> observers;
public:
void attach(Observer* observer) {
observers.push_back(observer);
}
void detach(Observer* observer) {
auto it = std::find(observers.begin(), observers.end(), observer);
if (it!= observers.end()) {
observers.erase(it);
}
}
void setTemperature(double temp) {
temperature = temp;
notifyObservers();
}
double getTemperature() const {
return temperature;
}
void notifyObservers() {
for (auto observer : observers) {
observer->update(temperature);
}
}
};
// 具体观察者类(显示设备)
class DisplayDevice : public Observer {
public:
void update(double temperature) override {
std::cout << "当前温度: " << temperature << "°C" << std::endl;
}
};
// 另一个具体观察者类(记录温度历史)
class TemperatureHistoryRecorder : public Observer {
private:
std::vector<double> history;
public:
void update(double temperature) override {
history.push_back(temperature);
std::cout << "记录温度: " << temperature << "°C,历史温度记录数量: " << history.size() << std::endl;
}
};
int main() {
WeatherStation station;
DisplayDevice device;
TemperatureHistoryRecorder recorder;
station.attach(&device);
station.attach(&recorder);
station.setTemperature(25.0);
station.detach(&device);
station.setTemperature(26.0);
return 0;
}
装饰模式
装饰模式理论:
装饰模式是一种结构型设计模式,它允许你动态地向一个对象添加新的行为,而不改变其接口。这种模式通过将对象放入包含行为的特殊封装对象(装饰器)中来实现。装饰模式提供了一种灵活的替代继承的方式来扩展对象的功能。
作者理解(大白话):
假如有三个功能分别是A,B,C 现在一个机器想装配这些功能,在装配后有7中可能,分别是 A,B,C,AB,AC,BC,ABC那么我们怎么实现装配的过程,如果不使用装配模式,会创建7中类用来分别创建这对应的七个模式,但是用了装配模式,就可以想加一个功能就执行加一个功能就可以了,代码不冗长,而且以后要想加D功能只需增加一个类就可以实现,例子代码如下
不使用装饰模式:
#include <iostream>
#include <string>
// 基础机器类,无任何功能
class BasicMachine {
public:
std::string perform() {
return "";
}
};
// 具有功能 A 的机器类
class MachineWithA {
private:
BasicMachine basicMachine;
public:
std::string perform() {
return basicMachine.perform() + "A";
}
};
// 具有功能 B 的机器类
class MachineWithB {
private:
BasicMachine basicMachine;
public:
std::string perform() {
return basicMachine.perform() + "B";
}
};
// 具有功能 C 的机器类
class MachineWithC {
private:
BasicMachine basicMachine;
public:
std::string perform() {
return basicMachine.perform() + "C";
}
};
// 具有功能 AB 的机器类
class MachineWithAB {
private:
MachineWithA machineWithA;
public:
std::string perform() {
return machineWithA.perform() + "B";
}
};
// 具有功能 AC 的机器类
class MachineWithAC {
private:
MachineWithA machineWithA;
public:
std::string perform() {
return machineWithA.perform() + "C";
}
};
// 具有功能 BC 的机器类
class MachineWithBC {
private:
MachineWithB machineWithB;
public:
std::string perform() {
return machineWithB.perform() + "C";
}
};
// 具有功能 ABC 的机器类
class MachineWithABC {
private:
MachineWithAB machineWithAB;
public:
std::string perform() {
return machineWithAB.perform() + "C";
}
};
int main() {
// 基础机器
BasicMachine basicMachine;
std::cout << "Basic Machine: " << basicMachine.perform() << std::endl;
// 装配功能 A
MachineWithA machineWithA;
std::cout << "Machine with A: " << machineWithA.perform() << std::endl;
// 装配功能 B
MachineWithB machineWithB;
std::cout << "Machine with B: " << machineWithB.perform() << std::endl;
// 装配功能 C
MachineWithC machineWithC;
std::cout << "Machine with C: " << machineWithC.perform() << std::endl;
// 装配功能 AB
MachineWithAB machineWithAB;
std::cout << "Machine with AB: " << machineWithAB.perform() << std::endl;
// 装配功能 AC
MachineWithAC machineWithAC;
std::cout << "Machine with AC: " << machineWithAC.perform() << std::endl;
// 装配功能 BC
MachineWithBC machineWithBC;
std::cout << "Machine with BC: " << machineWithBC.perform() << std::endl;
// 装配功能 ABC
MachineWithABC machineWithABC;
std::cout << "Machine with ABC: " << machineWithABC.perform() << std::endl;
return 0;
}
使用装饰模式后:
#include <iostream>
#include <string>
#include <memory>
// 抽象组件类:机器
class Machine {
public:
virtual ~Machine() {}
virtual std::string perform() = 0;
};
// 具体组件类:基础机器,无任何功能
class BasicMachine : public Machine {
public:
std::string perform() override {
return "";
}
};
// 抽象装饰类:机器功能装饰器
class MachineDecorator : public Machine {
protected:
std::unique_ptr<Machine> machine;
public:
MachineDecorator(std::unique_ptr<Machine> machine) : machine(std::move(machine)) {}
std::string perform() override {
return machine->perform();
}
};
// 具体装饰类:功能 A
class FunctionADecorator : public MachineDecorator {
public:
FunctionADecorator(std::unique_ptr<Machine> machine) : MachineDecorator(std::move(machine)) {}
std::string perform() override {
return machine->perform() + "A";
}
};
// 具体装饰类:功能 B
class FunctionBDecorator : public MachineDecorator {
public:
FunctionBDecorator(std::unique_ptr<Machine> machine) : MachineDecorator(std::move(machine)) {}
std::string perform() override {
return machine->perform() + "B";
}
};
// 具体装饰类:功能 C
class FunctionCDecorator : public MachineDecorator {
public:
FunctionCDecorator(std::unique_ptr<Machine> machine) : MachineDecorator(std::move(machine)) {}
std::string perform() override {
return machine->perform() + "C";
}
};
int main() {
// 基础机器
std::unique_ptr<Machine> basicMachine = std::make_unique<BasicMachine>();
std::cout << "Basic Machine: " << basicMachine->perform() << std::endl;
// 装配功能 A
std::unique_ptr<Machine> machineWithA = std::make_unique<FunctionADecorator>(std::move(basicMachine));
std::cout << "Machine with A: " << machineWithA->perform() << std::endl;
// 装配功能 B
std::unique_ptr<Machine> machineWithB = std::make_unique<FunctionBDecorator>(std::make_unique<BasicMachine>());
std::cout << "Machine with B: " << machineWithB->perform() << std::endl;
// 装配功能 C
std::unique_ptr<Machine> machineWithC = std::make_unique<FunctionCDecorator>(std::make_unique<BasicMachine>());
std::cout << "Machine with C: " << machineWithC->perform() << std::endl;
// 装配功能 AB
std::unique_ptr<Machine> machineWithAB = std::make_unique<FunctionBDecorator>(std::make_unique<FunctionADecorator>(std::make_unique<BasicMachine>()));
std::cout << "Machine with AB: " << machineWithAB->perform() << std::endl;
// 装配功能 AC
std::unique_ptr<Machine> machineWithAC = std::make_unique<FunctionCDecorator>(std::make_unique<FunctionADecorator>(std::make_unique<BasicMachine>()));
std::cout << "Machine with AC: " << machineWithAC->perform() << std::endl;
// 装配功能 BC
std::unique_ptr<Machine> machineWithBC = std::make_unique<FunctionCDecorator>(std::make_unique<FunctionBDecorator>(std::make_unique<BasicMachine>()));
std::cout << "Machine with BC: " << machineWithBC->perform() << std::endl;
// 装配功能 ABC
std::unique_ptr<Machine> machineWithABC = std::make_unique<FunctionCDecorator>(std::make_unique<FunctionBDecorator>(std::make_unique<FunctionADecorator>(std::make_unique<BasicMachine>()));
std::cout << "Machine with ABC: " << machineWithABC->perform() << std::endl;
return 0;
}
具体装饰模式的利用前后例子如下:
使用装饰模式之前:
#include <iostream>
#include <string>
// 抽象图形类
class Shape {
public:
virtual ~Shape() {}
virtual std::string draw() = 0;
};
// 具体图形类:圆形
class Circle : public Shape {
public:
std::string draw() override {
return "Drawing a Circle";
}
};
// 具体图形类:矩形
class Rectangle : public Shape {
public:
std::string draw() override {
return "Drawing a Rectangle";
}
};
// 具体图形类:红色圆形
class RedCircle : public Shape {
public:
std::string draw() override {
return "Drawing a Red Circle";
}
};
// 具体图形类:红色矩形
class RedRectangle : public Shape {
public:
std::string draw() override {
return "Drawing a Red Rectangle";
}
};
// 具体图形类:带边框的圆形
class BorderedCircle : public Shape {
public:
std::string draw() override {
return "Drawing a Bordered Circle";
}
};
// 具体图形类:带边框的矩形
class BorderedRectangle : public Shape {
public:
std::string draw() override {
return "Drawing a Bordered Rectangle";
}
};
// 具体图形类:红色带边框的圆形
class RedBorderedCircle : public Shape {
public:
std::string draw() override {
return "Drawing a Red Bordered Circle";
}
};
// 具体图形类:红色带边框的矩形
class RedBorderedRectangle : public Shape {
public:
std::string draw() override {
return "Drawing a Red Bordered Rectangle";
}
};
int main() {
Circle circle;
std::cout << circle.draw() << std::endl;
Rectangle rectangle;
std::cout << rectangle.draw() << std::endl;
RedCircle redCircle;
std::cout << redCircle.draw() << std::endl;
RedRectangle redRectangle;
std::cout << redRectangle.draw() << std::endl;
BorderedCircle borderedCircle;
std::cout << borderedCircle.draw() << std::endl;
BorderedRectangle borderedRectangle;
std::cout << borderedRectangle.draw() << std::endl;
RedBorderedCircle redBorderedCircle;
std::cout << redBorderedCircle.draw() << std::endl;
RedBorderedRectangle redBorderedRectangle;
std::cout << redBorderedRectangle.draw() << std::endl;
return 0;
}
使用装饰模式之后:
#include <iostream>
#include <string>
#include <memory>
// 抽象组件类:图形
class Shape {
public:
virtual ~Shape() {}
virtual std::string draw() = 0;
};
// 具体组件类:圆形
class Circle : public Shape {
public:
std::string draw() override {
return "Drawing a Circle";
}
};
// 具体组件类:矩形
class Rectangle : public Shape {
public:
std::string draw() override {
return "Drawing a Rectangle";
}
};
// 抽象装饰类:图形装饰器
class ShapeDecorator : public Shape {
protected:
std::unique_ptr<Shape> shape;
public:
ShapeDecorator(std::unique_ptr<Shape> shape) : shape(std::move(shape)) {}
std::string draw() override {
return shape->draw();
}
};
// 具体装饰类:红色装饰器
class RedShapeDecorator : public ShapeDecorator {
public:
RedShapeDecorator(std::unique_ptr<Shape> shape) : ShapeDecorator(std::move(shape)) {}
std::string draw() override {
return "Red " + shape->draw();
}
};
// 具体装饰类:边框装饰器
class BorderedShapeDecorator : public ShapeDecorator {
public:
BorderedShapeDecorator(std::unique_ptr<Shape> shape) : ShapeDecorator(std::move(shape)) {}
std::string draw() override {
return "Bordered " + shape->draw();
}
};
int main() {
// 绘制圆形
std::unique_ptr<Shape> circle = std::make_unique<Circle>();
std::cout << circle->draw() << std::endl;
// 绘制红色圆形
std::unique_ptr<Shape> redCircle = std::make_unique<RedShapeDecorator>(std::make_unique<Circle>());
std::cout << redCircle->draw() << std::endl;
// 绘制带边框的圆形
std::unique_ptr<Shape> borderedCircle = std::make_unique<BorderedShapeDecorator>(std::make_unique<Circle>());
std::cout << borderedCircle->draw() << std::endl;
// 绘制红色带边框的圆形
std::unique_ptr<Shape> redBorderedCircle = std::make_unique<BorderedShapeDecorator>(std::make_unique<RedShapeDecorator>(std::make_unique<Circle>()));
std::cout << redBorderedCircle->draw() << std::endl;
// 绘制矩形
std::unique_ptr<Shape> rectangle = std::make_unique<Rectangle>();
std::cout << rectangle->draw() << std::endl;
// 绘制红色矩形
std::unique_ptr<Shape> redRectangle = std::make_unique<RedShapeDecorator>(std::make_unique<Rectangle>());
std::cout << redRectangle->draw() << std::endl;
// 绘制带边框的矩形
std::unique_ptr<Shape> borderedRectangle = std::make_unique<BorderedShapeDecorator>(std::make_unique<Rectangle>());
std::cout << borderedRectangle->draw() << std::endl;
// 绘制红色带边框的矩形
std::unique_ptr<Shape> redBorderedRectangle = std::make_unique<BorderedShapeDecorator>(std::make_unique<RedShapeDecorator>(std::make_unique<Rectangle>()));
std::cout << redBorderedRectangle->draw() << std::endl;
return 0;
}
桥模式
桥模式理论:
桥接模式(Bridge Pattern)是一种结构型设计模式。它将抽象部分与它的实现部分分离,使它们都可以独立地变化。这种分离可以让系统的结构更加灵活,并且能够更好地应对软件系统在演化过程中可能出现的变化
作者理解大白话:
在一个类中,如果类的作用不够单一,在面对后续的变化的时候要修改代码,违反开闭原则,为了更单一,就分成多个类,比如一个类CarService负责汽车业务此时有贴膜业务和喷漆业务,如果后续想对喷漆业务增加油漆种类的话,那么代码都要在A类中修改,那么在使用桥模式后,以CarService作为基类,贴膜业务和喷漆业务作为子类,那么将来对喷漆业务后续进行派生或者增加业务时候,那么和贴膜业务互不干扰,互相职责单一,对代码的可读性维护性有重要作用,况且日后还想增加A的子类比如说维修业务,那么把维修业务单独作为一个CarService的子类增加就可以了,而不是三个业务堆在一个类里面,后续的业务变化相互影响,复杂难读。
上述例子代码如下:(不懂的话可以让AI说明)
#include <iostream>
#include <string>
// 实现化角色接口:汽车服务接口
class CarService {
public:
virtual void performService() = 0;
};
// 具体实现化角色:贴膜服务
class FilmService : public CarService {
public:
void performService() override {
std::cout << "Performing film service." << std::endl;
}
};
// 具体实现化角色:喷漆服务接口
class PaintService : public CarService {
public:
virtual void paintWith(std::string paintType) = 0;
};
// 具体实现化角色:喷漆服务的具体实现
class StandardPaintService : public PaintService {
public:
void paintWith(std::string paintType) override {
std::cout << "Painting the car with " << paintType << " paint." << std::endl;
}
};
// 抽象化角色:汽车业务基类
class CarBusiness {
protected:
CarService* service;
public:
CarBusiness(CarService* s) : service(s) {}
virtual void executeService() = 0;
};
// 扩展抽象化角色:贴膜业务
class FilmBusiness : public CarBusiness {
public:
FilmBusiness(CarService* s) : CarBusiness(s) {}
void executeService() override {
service->performService();
}
};
// 扩展抽象化角,色:喷漆业务
class PaintBusiness : public CarBusiness {
public:
PaintBusiness(CarService* s) : CarBusiness(s) {}
void executeService() override {
// 假设使用红色油漆,可根据需要修改
std::string paintType = "Red";
dynamic_cast<PaintService*>(service)->paintWith(paintType);
}
};
int main() {
// 执行贴膜业务
FilmService filmService;
FilmBusiness filmBusiness(&filmService);
filmBusiness.executeService();
// 执行喷漆业务
StandardPaintService paintService;
PaintBusiness paintBusiness(&paintService);
paintBusiness.executeService();
return 0;
}
具体桥模式的利用前后例子如下:
使用前:
#include <iostream>
#include <string>
// 电视机类
class TV {
public:
void on() {
std::cout << "TV is turned on." << std::endl;
}
void off() {
std::cout << "TV is turned off." << std::endl;
}
void tuneChannel(int channel) {
std::cout << "TV is tuned to channel " << channel << std::endl;
}
};
// 收音机类
class Radio {
public:
void on() {
std::cout << "Radio is turned on." << std::endl;
}
void off() {
std::cout << "Radio is turned off." << std::endl;
}
void setFrequency(double frequency) {
std::cout << "Radio is set to frequency " << frequency << std::endl;
}
};
// 简单遥控器类,专门控制电视机
class SimpleRemoteForTV {
private:
TV tv;
public:
void power() {
tv.on();
}
void channelUp() {
std::cout << "Channel up on TV." << std::endl;
}
void channelDown() {
std::cout << "Channel down on TV." << std::endl;
}
};
// 简单遥控器类,专门控制收音机
class SimpleRemoteForRadio {
private:
Radio radio;
public:
void power() {
radio.on();
}
void volumeUp() {
std::cout << "Volume up on Radio." << std::endl;
}
void volumeDown() {
std::cout << "Volume down on Radio." << std::endl;
}
};
// 高级遥控器类,专门控制电视机
class AdvancedRemoteForTV {
private:
TV tv;
public:
void power() {
tv.on();
}
void channelUp() {
std::cout << "Channel up on TV." << std::endl;
}
void channelDown() {
std::cout << "Channel down on TV." << std::endl;
}
void mute() {
std::cout << "TV is muted." << std::endl;
}
};
// 高级遥控器类,专门控制收音机
class AdvancedRemoteForRadio {
private:
Radio radio;
public:
void power() {
radio.on();
}
void volumeUp() {
std::cout << "Volume up on Radio." << std::endl;
}
void volumeDown() {
std::cout << "Volume down on Radio." << std::endl;
}
void mute() {
std::cout << "Radio is muted." << std::endl;
}
};
int main() {
SimpleRemoteForTV simpleRemoteForTV;
simpleRemoteForTV.power();
simpleRemoteForTV.channelUp();
SimpleRemoteForRadio simpleRemoteForRadio;
simpleRemoteForRadio.power();
simpleRemoteForRadio.volumeUp();
AdvancedRemoteForTV advancedRemoteForTV;
advancedRemoteForTV.power();
advancedRemoteForTV.mute();
AdvancedRemoteForRadio advancedRemoteForRadio;
advancedRemoteForRadio.power();
advancedRemoteForRadio.mute();
return 0;
}
说明:
对于不同的设备(TV 和 Radio)和不同的遥控器(SimpleRemote 和 AdvancedRemote),我们为每种设备和遥控器的组合创建了一个专门的类。
这样会导致类的数量快速增长,代码冗余且难以维护,因为每个遥控器类都包含了对设备的具体操作,并且有很多重复的代码。
当添加新的设备或新的遥控器功能时,需要创建更多的类,例如,如果要添加一个新的设备,如 DVD 播放器,就需要创建 SimpleRemoteForDVD
和 AdvancedRemoteForDVD
等类,不符合开闭原则。
使用后:
#include <iostream>
#include <string>
#include <memory>
// 设备接口
class Device {
public:
virtual ~Device() {}
virtual void on() = 0;
virtual void off() = 0;
virtual void volumeUp() = 0;
virtual void volumeDown() = 0;
virtual void channelUp() = 0;
virtual void channelDown() = 0;
virtual void mute() = 0;
};
// 电视机类,实现设备接口
class TV : public Device {
public:
void on() override {
std::cout << "TV is turned on." << std::endl;
}
void off() override {
std::cout << "TV is turned off." << std::endl;
}
void volumeUp() override {
std::cout << "Volume up on TV." << std::endl;
}
void volumeDown() override {
std::cout << "Volume down on TV." << std::endl;
}
void channelUp() override {
std::cout << "Channel up on TV." << std::endl;
}
void channelDown() override {
std::cout << "Channel down on TV." << std::endl;
}
void mute() override {
std::cout << "TV is muted." << std::endl;
}
};
// 收音机类,实现设备接口
class Radio : public Device {
public:
void on() override {
std::cout << "Radio is turned on." << std::endl;
}
void off() override {
std::cout << "Radio is turned off." << std::endl;
}
void volumeUp() override {
std::cout << "Volume up on Radio." << std::endl;
}
void volumeDown() override {
std::cout << "Volume down on Radio." << std::endl;
}
void channelUp() override {
std::cout << "Channel up on Radio." << std::endl;
}
void channelDown() override {
std::cout << "Channel down on Radio." << std::endl;
}
void mute() override {
std::cout << "Radio is muted." << std::endl;
}
};
// 遥控器抽象类
class Remote {
protected:
std::unique_ptr<Device> device;
public:
Remote(std::unique_ptr<Device> device) : device(std::move(device)) {}
virtual void power() = 0;
virtual void volumeUp() {
device->volumeUp();
}
virtual void volumeDown() {
device->volumeDown();
}
virtual void channelUp() {
device->channelUp();
}
virtual void channelDown() {
device->channelDown();
}
virtual void mute() {
device->mute();
}
};
// 简单遥控器类
class SimpleRemote : public Remote {
public:
SimpleRemote(std::unique_ptr<Device> device) : Remote(std::move(device)) {}
void power() override {
device->on();
}
};
// 高级遥控器类
class AdvancedRemote : public Remote {
public:
AdvancedRemote(std::unique_ptr<Device> device) : Remote(std::move(device)) {}
void power() override {
device->on();
}
void mute() override {
device->mute();
}
};
int main() {
std::unique_ptr<Device> tv = std::make_unique<TV>();
std::unique_ptr<Remote> simpleRemoteForTV = std::make_unique<SimpleRemote>(std::move(tv));
simpleRemoteForTV->power();
simpleRemoteForTV->channelUp();
std::unique_ptr<Device> radio = std::make_unique<Radio>();
std::unique_ptr<Remote> simpleRemoteForRadio = std::make_unique<SimpleRemote>(std::move(radio));
simpleRemoteForRadio->power();
simpleRemoteForRadio->volumeUp();
std::unique_ptr<Device> tv2 = std::make_unique<TV>();
std::unique_ptr<Remote> advancedRemoteForTV = std::make_unique<AdvancedRemote>(std::move(tv2));
advancedRemoteForTV->power();
advancedRemoteForTV->mute();
std::unique_ptr<Device> radio2 = std::make_unique<Radio>();
std::unique_ptr<Remote> advancedRemoteForRadio = std::make_unique<AdvancedRemote>(std::move(radio2));
advancedRemoteForRadio->power();
advancedRemoteForRadio->mute();
return 0;
}
说明:
设备接口 Device
:定义了设备的通用操作,如 on
、off
、volumeUp
等。
具体设备类 TV
和 Radio
:实现了 Device
接口,提供具体设备的操作。
遥控器抽象类 Remote
:包含一个 Device
的指针,在构造函数中接收 Device
对象,并提供遥控器的操作接口,将操作委托给 Device
对象。
具体遥控器类 SimpleRemote
和 AdvancedRemote
:继承自 Remote
,实现不同类型遥控器的操作,将操作通过 Device
指针转发给具体设备。
对比分析:
使用前:
对于不同的设备和遥控器组合,需要创建多个类,导致代码冗余,可扩展性差,例如添加新设备或新功能时,需要创建大量新类。不同遥控器类中存在大量重复代码,维护困难
使用后:可以灵活组合不同的设备和遥控器,添加新设备或新遥控器功能时,只需要创建新的设备类或遥控器类,无需修改现有代码,符合开闭原则。只需要创建具体设备类和具体遥控器类,通过桥接模式将它们解耦,实现了设备和遥控器的分离。
使用桥接模式的好处:
解耦:将抽象部分(遥控器)和实现部分(设备)分离,使它们可以独立地变化和扩展。
可扩展性:添加新设备或新遥控器功能变得更加容易,只需要添加新的设备类或遥控器类,而不是为每种组合创建新类。
代码简洁:减少了代码冗余,提高了代码的可维护性和可读性。
工厂模式:
工厂模式理论:
工厂模式是一种创建对象的设计模式,它提供了一种创建对象的方式,将对象的创建和使用分离,使得代码更加灵活、可维护和可扩展。以下是对工厂模式的详细解释:
作者理解(大白话):
大家都知道,一个类可以调用类内部的方法,但我们想知道这个类必须要把他的名字写对,这就是实现细节,但是设计模式告诉我们,编译时依赖不如运行时依赖,给了车作为基类,法拉利,奔驰,宝马作为其子类,在这三种车的类想调用“保养”这个方法的时候,我们不希望直接写他们的名字,要用车这个基类的指针指向子类对象,那么这个子类对象我们也不希望是一个实打实的名字,这就是“把子类的创建和子类的使用隔离开的方法”,目的是以后更好的应对变化,比如又加了一辆兰博基尼,那么可以保证这个兰博基尼的使用的时候可以使用前一套法拉利和奔驰的办法,那么工厂模式就是想让基类指针明白他所指向的是谁,此时就需要工厂处理,可以定义车工厂作为基类,再以法拉利工厂,奔驰工厂,宝马工厂作为子类在想创建宝马车对象的时候,只需要调用宝马车工厂就可以获得宝马车,这样分离对象的创建和使用,使得代码更简介易维护,而且满足了开闭原则。下面就是车工厂的示例
#include <iostream>
#include <string>
using namespace std;
// 抽象车基类
class Car
{
public:
virtual void introduce() = 0;
virtual ~Car() {} // 提供虚析构函数定义
};
class BMW: public Car//宝马车
{
public:
virtual void introduce()override
{
cout << "我宝马车最牛逼" << endl;
}
};
class FLL :public Car //法拉利
{
public:
virtual void introduce()override
{
cout << "我法拉利最牛逼" << endl;
}
};
class BC : public Car
{
public:
virtual void introduce()override
{
cout << "我奔驰车最牛逼" << endl;
}
};
class Factory//工厂基类
{
protected:
virtual Car* CreatCar() = 0;
virtual ~Factory(){}
};
class BMWFactory :public Factory//宝马车工厂
{
public:
virtual Car* CreatCar()override
{
return new BMW;
}
};
class FLLFactory :public Factory//法拉利工厂
{
public:
virtual Car* CreatCar()override
{
return new FLL;
}
};
class BCFactory : public Factory//奔驰工厂
{
public:
virtual Car* CreatCar()override
{
return new BC;
}
};
int main()
{
BMWFactory bmwfactory;
Car* car = bmwfactory.CreatCar();
car->introduce();
delete car;
}
具体工厂模式的利用前后例子如下:
这次我们以创建不同类型的电子产品(如手机、电脑和平板)为例:
使用前:
#include <iostream>
#include <string>
// 抽象电子产品类
class ElectronicProduct {
public:
virtual void display() = 0;
virtual ~ElectronicProduct() {}
};
// 具体产品类:手机
class Phone : public ElectronicProduct {
public:
void display() override {
std::cout << "This is a phone." << std::endl;
}
};
// 具体产品类:电脑
class Computer : public ElectronicProduct {
public:
void display() override {
std::cout << "This is a computer." << std::endl;
}
};
// 具体产品类:平板
class Tablet : public ElectronicProduct {
public:
void display() override {
std::cout << "This is a tablet." << std::endl;
}
};
int main() {
// 直接创建对象
ElectronicProduct* product1 = new Phone();
ElectronicProduct* product2 = new Computer();
ElectronicProduct* product3 = new Tablet();
product1->display();
product2->display();
product3->display();
// 手动释放内存
delete product1;
delete product2;
delete product3;
return 0;
}
使用后:
代码解释:
ElectronicProduct
是一个抽象类,定义了 display
纯虚函数,用于显示产品信息。Phone
、Computer
和 Tablet
是具体的产品类,它们继承自 ElectronicProduct
并实现了 display
函数。在 main
函数中,直接使用 new
创建不同类型的电子产品对象,并调用 display
方法展示信息。最后使用 delete
手动释放对象,避免内存泄漏。
使用后:
#include <iostream>
#include <string>
#include <memory>
// 抽象电子产品类
class ElectronicProduct {
public:
virtual void display() = 0;
virtual ~ElectronicProduct() {}
};
// 具体产品类:手机
class Phone : public ElectronicProduct {
public:
void display() override {
std::cout << "This is a phone." << std::endl;
}
};
// 具体产品类:电脑
class Computer : public ElectronicProduct {
public:
void display() override {
std::cout << "This is a computer." << std::endl;
}
};
// 具体产品类:平板
class Tablet : public ElectronicProduct {
public:
void display() override {
std::cout << "This is a tablet." << std::endl;
}
};
// 抽象工厂类
class ElectronicFactory {
protected:
virtual ElectronicProduct* createProduct() = 0;
virtual ~ElectronicFactory() {}
};
// 具体工厂类:手机工厂
class PhoneFactory : public ElectronicFactory {
public:
ElectronicProduct* createProduct() override {
return new Phone();
}
};
// 具体工厂类:电脑工厂
class ComputerFactory : public ElectronicFactory {
public:
ElectronicProduct* createProduct() override {
return new Computer();
}
};
// 具体工厂类:平板工厂
class TabletFactory : public ElectronicFactory {
public:
ElectronicProduct* createProduct() override {
return new Tablet();
}
};
int main() {
// 使用工厂模式创建对象
std::unique_ptr<ElectronicFactory> phoneFactory = std::make_unique<PhoneFactory>();
std::unique_ptr<ElectronicProduct> phone = std::unique_ptr<ElectronicProduct>(phoneFactory->createProduct());
phone->display();
std::unique_ptr<ElectronicFactory> computerFactory = std::make_unique<ComputerFactory>();
std::unique_ptr<ElectronicProduct> computer = std::unique_ptr<ElectronicProduct>(computerFactory->createProduct());
computer->display();
std::unique_ptr<ElectronicFactory> tabletFactory = std::make_unique<TabletFactory>();
std::unique_ptr<ElectronicProduct> tablet = std::unique_ptr<ElectronicProduct>(tabletFactory->createProduct());
tablet->display();
// 智能指针会自动释放对象,无需手动删除
return 0;
}
代码解释:
除了产品类的定义外,我们引入了 ElectronicFactory
作为抽象工厂类,它有一个纯虚函数 createProduct
用于创建电子产品。PhoneFactory
、ComputerFactory
和 TabletFactory
是具体的工厂类,分别实现了 createProduct
方法,用于创建相应的电子产品。在 main
函数中,使用 std::make_unique
创建工厂对象和产品对象,通过工厂对象的 createProduct
方法创建具体产品。使用 std::unique_ptr
智能指针管理对象,当智能指针超出作用域时,会自动调用析构函数释放对象,避免手动删除对象。
对比分析:
-
可维护性:
- 不使用工厂模式:
- 当需要添加新的电子产品时,需要在
main
函数中添加新的new
和delete
操作,使得main
函数变得臃肿,不易维护。 - 例如,如果要添加一个新的产品,如
Laptop
,需要修改main
函数。
- 当需要添加新的电子产品时,需要在
- 使用工厂模式:
- 只需要添加新的产品类(如
Laptop
类)和相应的工厂类(如LaptopFactory
类),并实现相应的方法,而main
函数的代码结构无需改变。
- 只需要添加新的产品类(如
- 不使用工厂模式:
-
可扩展性:
- 不使用工厂模式:
- 不符合开闭原则,即对扩展开放,对修改关闭。添加新的产品需要修改已有的代码(如
main
函数)。
- 不符合开闭原则,即对扩展开放,对修改关闭。添加新的产品需要修改已有的代码(如
- 使用工厂模式:
- 更符合开闭原则,添加新的产品只需要添加新的类和工厂类,而不修改现有代码。
- 不使用工厂模式:
-
代码耦合度:
- 不使用工厂模式:
main
函数与具体产品的创建逻辑紧密耦合,直接依赖具体产品的实现。
- 使用工厂模式:
main
函数只依赖抽象工厂和抽象产品,不依赖具体产品的创建细节,降低了耦合度。
- 不使用工厂模式:
通过使用工厂模式,代码变得更加可维护、可扩展,并且降低了代码的耦合度,更符合面向对象设计的原则,特别是在需要创建多种类型对象的情况下,工厂模式可以使代码结构更加清晰,易于管理。
构建器
先说一点:构造函数只可以运用于本类,若是虚函数那也将调用虚函数,
构建模式理论:
Builder 模式是一种创建型设计模式。它的主要目的是将一个复杂对象的构建过程和它的表示分离,使得同样的构建过程可以创建不同的表示。在 C++ 中,这种模式尤其适用于创建具有多个可选参数或者复杂初始化过程的对象。
作者理解(大白话):
构建模式和工厂模式最大的区别就是,构建模式是一个对象但是样复杂的创建,工厂模式的多个类简易(也可能复杂)的分开创建,举例而言对一个车来说如果考虑车轮车窗等等,那就一个车多样那就构建模式,但是分为法拉利,奔驰等等不同车那就是工厂模式
建议大家把下面这段代码好好的理解一下:
#include <iostream>
#include <string>
#include <memory>
// 产品类:电脑
class Computer {
private:
std::string cpu;
std::string gpu;
int memory;
int storage;
public:
void setCpu(const std::string& cpu) {
this->cpu = cpu;
}
void setGpu(const std::string& gpu) {
this->gpu = gpu;
}
void setMemory(int memory) {
this->memory = memory;
}
void setStorage(int storage) {
this->storage = storage;
}
void display() const {
std::cout << "CPU: " << cpu << std::endl;
std::cout << "GPU: " << gpu << std::endl;
std::cout << "Memory: " << memory << "GB" << std::endl;
std::cout << "Storage: " << storage << "GB" << std::endl;
}
};
// 抽象建造者类
class ComputerBuilder {
public:
virtual void buildCpu() = 0;
virtual void buildGpu() = 0;
virtual void buildMemory() = 0;
virtual void buildStorage() = 0;
virtual Computer* getComputer() = 0;
virtual ~ComputerBuilder() = default;
};
// 具体建造者类:游戏电脑建造者
class GamingComputerBuilder : public ComputerBuilder {
private:
Computer* computer;
public:
GamingComputerBuilder() : computer(new Computer()) {}
void buildCpu() override {
computer->setCpu("Intel Core i9 - 13900K");
}
void buildGpu() override {
computer->setGpu("NVIDIA RTX 4090");
}
void buildMemory() override {
computer->setMemory(32);
}
void buildStorage() override {
computer->setStorage(2000);
}
Computer* getComputer() override {
return computer;
}
~GamingComputerBuilder() {
delete computer;
}
};
// 指挥者类
class ComputerDirector {
public:
Computer* constructComputer(ComputerBuilder* builder) {
builder->buildCpu();
builder->buildGpu();
builder->buildMemory();
builder->buildStorage();
return builder->getComputer();
}
};
// 测试Builder模式
int main() {
ComputerDirector director;
GamingComputerBuilder builder;
Computer* gamingComputer = director.constructComputer(&builder);
gamingComputer->display();
delete gamingComputer;
return 0;
}
享元模式:
享元模式理论:
亨元模式(Flyweight Pattern)是一种结构型设计模式,它主要用于减少创建对象的数量,以降低内存使用和提高性能。该模式尝试重用现有的同类对象,如果没有匹配的对象,则创建新对象。
作者理解(大白话):
对于一类对象,我们可能要重复创建它们,但是创建后可能两个对象一模一样,为了使一模一样的对象变为一个,我们直接在创建的时候把它变为一个就可以了
#include <iostream>
#include <unordered_map>
class Flyweight {
public:
virtual void operation(int extrinsicState) = 0;
virtual ~Flyweight() = default;
};
class ConcreteFlyweight : public Flyweight {
private:
int intrinsicState;
public:
ConcreteFlyweight(int state) : intrinsicState(state) {}
void operation(int extrinsicState) override {
std::cout << "ConcreteFlyweight: " << intrinsicState << " with extrinsic state: " << extrinsicState << std::endl;
}
};
class FlyweightFactory {
private:
std::unordered_map<int, Flyweight*> pool;
public:
Flyweight* getFlyweight(int key) {
if (pool.count(key) == 0) {
pool[key] = new ConcreteFlyweight(key);
}
return pool[key];
}
~FlyweightFactory() {
for (auto& pair : pool) {
delete pair.second;
}
}
};
int main() {
FlyweightFactory factory;
Flyweight* fw1 = factory.getFlyweight(1);
fw1->operation(10);
Flyweight* fw2 = factory.getFlyweight(1);
fw2->operation(20);
// fw1 和 fw2 应该是同一个对象,因为它们的内部状态相同
return 0;
}
这里已经创建了fw1,但是我后面又想创建fw2,但是fw2的内部和fw1是一样的,为了防止过多开销,直接不创建,在想创建fw2的时候直接找到fw1并返回出去
代理模式
代理模式理论:
代理模式为其他对象提供一种代理以控制对这个对象的访问。
作者理解(大白话):
假设我们正在开发一个在线图书馆系统,有一个 BookManager
类负责管理图书的借阅操作。在借阅图书之前,需要检查用户是否有借阅权限,借阅完成后需要记录借阅日志。如果不使用代理模式,直接调用 BookManager
的借阅方法,就无法方便地添加权限检查和日志记录功能。那么就需要用到代理模式,进行对借阅操作的控制,就是权限检查和日志记录等等
没使用之前:
#include <iostream>
#include <string>
#include <vector>
// 表示用户的类
class User {
public:
User(const std::string& id, bool hasPermission) : userId(id), canBorrow(hasPermission) {}
std::string getUserId() const {
return userId;
}
bool canBorrowBook() const {
return canBorrow;
}
private:
std::string userId;
bool canBorrow;
};
// 表示图书的类
class Book {
public:
Book(const std::string& title) : bookTitle(title) {}
std::string getTitle() const {
return bookTitle;
}
private:
std::string bookTitle;
};
// 图书管理类,负责图书借阅操作
class BookManager {
public:
void borrowBook(const User& user, const Book& book) {
std::cout << "Borrowing book: " << book.getTitle() << " for user: " << user.getUserId() << std::endl;
}
};
// 客户端代码,直接使用 BookManager 进行图书借阅
int main() {
User user("user001", true);
Book book("C++ Primer");
BookManager bookManager;
// 直接调用借阅方法,没有权限检查和日志记录
bookManager.borrowBook(user, book);
return 0;
}
使用之后:
#include <iostream>
#include <string>
#include <vector>
// 表示用户的类
class User {
public:
User(const std::string& id, bool hasPermission) : userId(id), canBorrow(hasPermission) {}
std::string getUserId() const {
return userId;
}
bool canBorrowBook() const {
return canBorrow;
}
private:
std::string userId;
bool canBorrow;
};
// 表示图书的类
class Book {
public:
Book(const std::string& title) : bookTitle(title) {}
std::string getTitle() const {
return bookTitle;
}
private:
std::string bookTitle;
};
// 抽象借阅接口
class Borrowable {
public:
virtual void borrowBook(const User& user, const Book& book) = 0;
virtual ~Borrowable() {}
};
// 图书管理类,实现借阅接口
class BookManager : public Borrowable {
public:
void borrowBook(const User& user, const Book& book) override {
std::cout << "Borrowing book: " << book.getTitle() << " for user: " << user.getUserId() << std::endl;
}
};
// 代理类,也实现借阅接口
class BookManagerProxy : public Borrowable {
private:
BookManager* realBookManager;
// 权限检查方法
bool checkPermission(const User& user) {
if (user.canBorrowBook()) {
std::cout << "Permission check passed for user: " << user.getUserId() << std::endl;
return true;
} else {
std::cout << "Permission check failed for user: " << user.getUserId() << std::endl;
return false;
}
}
// 日志记录方法
void logBorrow(const User& user, const Book& book) {
std::cout << "Logging: User " << user.getUserId() << " borrowed book " << book.getTitle() << std::endl;
}
public:
BookManagerProxy() : realBookManager(new BookManager()) {}
~BookManagerProxy() {
delete realBookManager;
}
void borrowBook(const User& user, const Book& book) override {
if (checkPermission(user)) {
realBookManager->borrowBook(user, book);
logBorrow(user, book);
}
}
};
// 客户端代码,通过代理类进行图书借阅
int main() {
User user("user001", true);
Book book("C++ Primer");
BookManagerProxy proxy;
proxy.borrowBook(user, book);
return 0;
}
适配器模式
适配器模式理论:
适配器模式是一种结构型设计模式,其核心目的是让原本由于接口不兼容而不能一起工作的类能够协同工作。下面从多个方面详细介绍适配器模式的理论知识:
基本概念
适配器模式就像现实生活中的电源适配器,它可以将一种接口转换为另一种接口,以满足不同设备的需求。在软件开发中,当需要使用一个现有的类,但其接口与当前系统要求的接口不一致时,就可以使用适配器模式来解决这个问题。
角色构成
适配器模式主要包含以下三个角色:
目标接口(Target):定义了客户端所期望使用的接口,它是客户端代码调用的接口标准。目标接口可以是抽象类、接口(在 C++ 中通过纯虚函数实现类似接口的概念),它规定了客户端使用的方法和行为。
适配者(Adaptee):已经存在的类,它包含了客户端需要的功能,但它的接口与目标接口不兼容。适配者类是需要被适配的对象,其方法和参数可能与目标接口不同
适配器(Adapter):适配器是适配器模式的核心,它实现了目标接口,并持有一个适配者对象的引用。适配器类负责将目标接口的方法调用转换为适配者类的方法调用,从而完成接口的转换。
实现方式
适配器模式有两种常见的实现方式:类适配器和对象适配器。
类适配器:类适配器使用多重继承来实现,适配器类同时继承自目标接口和适配者类。通过这种方式,适配器类可以直接重写目标接口的方法,并调用适配者类的方法来完成功能。类适配器的优点是实现简单,缺点是由于使用了多重继承,可能会导致代码的复杂性增加,并且在一些编程语言中(如 Java)不支持多重继承
对象适配器:对象适配器通过组合的方式实现,适配器类实现了目标接口,并持有一个适配者对象的引用。在适配器类的方法中,通过调用适配者对象的方法来完成功能。对象适配器的优点是更加灵活,不需要依赖于继承,并且可以适配多个不同的适配者类;缺点是需要额外创建适配者对象,可能会增加一些内存开销。
优点
提高代码复用性:适配器模式可以让已有的类在不改变其代码的情况下,适配到新的接口上,从而实现代码的复用,避免了重复开发。
增强系统兼容性:在集成不同的系统、模块或库时,适配器模式可以解决接口不兼容的问题,使它们能够协同工作,提高了系统的兼容性和可扩展性。
符合开闭原则:适配器模式遵循开闭原则,即对扩展开放,对修改关闭。当需要适配新的类或接口时,只需要创建新的适配器类,而不需要修改现有的客户端代码。
作者大白话理解:
想象你去国外旅行,你携带的手机充电器插头是国内标准的,而当地的插座是另一种标准,你的充电器插头根本插不进去当地插座,这时候手机就没法充电。不过别担心,你可以买一个电源适配器。这个电源适配器一头能适配你手机充电器的插头,另一头能插进当地的插座。通过这个电源适配器,原本不兼容的手机充电器和当地插座就能协同工作,手机也就能顺利充电了。在编程里,这就好比有一个现有的类(类似手机充电器),它有自己特定的功能和接口,但这个接口和我们当前系统需要的接口(类似当地插座)不匹配。适配器模式就像这个电源适配器,它把现有的类的接口转换成系统期望的接口,让这个现有的类能在新系统里正常使用。
#include <iostream>
// 目标接口:当地插座标准
class LocalSocket {
public:
virtual void plugIn() = 0;
virtual ~LocalSocket() {}
};
// 适配者类:国内充电器
class ChineseCharger {
public:
void chargeWithChinesePlug() {
std::cout << "Charging with Chinese plug." << std::endl;
}
};
// 类适配器:电源适配器
class PowerAdapter : public LocalSocket, private ChineseCharger {
public:
void plugIn() override {
chargeWithChinesePlug();
}
};
// 客户端代码
int main() {
LocalSocket* adapter = new PowerAdapter();
adapter->plugIn();
delete adapter;
return 0;
}
中介者模式
理论:
1. 中介者模式的定义与概念
中介者模式(Mediator Pattern)是一种行为设计模式,它允许你减少对象之间混乱无序的依赖关系。该模式通过引入一个中介者对象,来封装一系列对象之间的交互,使得各个对象之间不需要显式地相互引用,从而降低了对象之间的耦合度,并且可以独立地改变它们之间的交互。
简单来说,中介者模式就像是一个协调中心,各个对象之间的通信都通过这个中介者来进行,而不是直接相互通信。
2. 中介者模式的角色与结构
中介者模式通常包含以下几个角色:
抽象中介者(Mediator):定义了中介者与各个同事对象之间通信的接口,通常包含一个或多个抽象方法,用于处理同事对象之间的交互请求。
具体中介者(Concrete Mediator):实现了抽象中介者定义的接口,负责协调各个同事对象之间的交互。具体中介者需要了解并维护各个同事对象的引用,根据不同的交互请求进行相应的处理。
抽象同事类(Colleague):定义了同事对象的基本接口,通常包含一个指向中介者对象的引用,以及一些与中介者进行通信的方法。
具体同事类(Concrete Colleague):继承自抽象同事类,实现了具体的业务逻辑。具体同事类之间不直接进行通信,而是通过中介者来间接通信。
作者理解(大白话):
中介者模式就是给各个人之间一个交流的平台,而不只是1对1的依赖关系,5个人的对话都可以传给中介者,中介者可以给其他人传话,而不1号直接找2号这种
代码展示:
这个代码比较小复杂,主要就是,房产中介可以给买家或者卖家一个发消息的平台,理解即可
-
抽象同事类
Participant
:- 包含一个指向中介者的引用
mediator
和参与者的唯一标识id
。 - 定义了纯虚函数
send
和receive
,分别用于发送和接收消息。
- 包含一个指向中介者的引用
-
抽象中介者
RealEstateMediator
:- 定义了
addParticipant
方法,用于添加参与者到系统中。 sendMessage
方法用于处理消息的传递。verifyInfo
方法用于验证参与者的信息。
- 定义了
-
具体同事类
Buyer
:- 有一个
interestedProperties
列表,记录买家感兴趣的房产。 showInterestInProperty
方法用于表达买家对某个房产的兴趣,并通过中介向所有卖家发送消息。
- 有一个
-
具体同事类
Seller
:- 使用
properties
哈希表来存储卖家列出的房产信息。 listProperty
方法用于列出房产,并通过中介向所有买家发送消息。respondToInterest
方法用于卖家对买家的询问进行回复。
- 使用
-
具体中介者
RealEstateAgent
:- 使用
participants
哈希表来管理所有参与者。 verifiedInfo
哈希表记录参与者信息的验证状态。addParticipant
方法添加参与者并进行信息验证。sendMessage
方法根据目标 ID 将消息传递给相应的参与者,可以是单个参与者、所有买家或所有卖家。verifyInfo
方法模拟验证参与者信息的过程。
- 使用
-
客户端代码:
- 创建房产中介、买家和卖家对象。
- 将参与者添加到中介系统中。
- 卖家列出房产,买家表达兴趣,卖家进行回复。
- 最后释放所有对象的内存。
#include <iostream>
#include <string>
#include <vector>
#include <unordered_map>
// 前向声明
class RealEstateMediator;
// 抽象同事类
class Participant {
protected:
RealEstateMediator* mediator;
std::string id;
public:
Participant(const std::string& participantId, RealEstateMediator* m) : id(participantId), mediator(m) {}
virtual void send(const std::string& message, const std::string& targetId) = 0;
virtual void receive(const std::string& message) = 0;
std::string getId() const { return id; }
};
// 抽象中介者
class RealEstateMediator {
public:
virtual void addParticipant(Participant* participant) = 0;
virtual void sendMessage(const std::string& message, const std::string& senderId, const std::string& targetId) = 0;
virtual void verifyInfo(const std::string& participantId) = 0;
};
// 具体同事类:买家
class Buyer : public Participant {
private:
std::vector<std::string> interestedProperties;
public:
Buyer(const std::string& buyerId, RealEstateMediator* m) : Participant(buyerId, m) {}
void send(const std::string& message, const std::string& targetId) override {
std::cout << "Buyer " << id << " sends: " << message << " to " << targetId << std::endl;
mediator->sendMessage(message, id, targetId);
}
void receive(const std::string& message) override {
std::cout << "Buyer " << id << " receives: " << message << std::endl;
}
void showInterestInProperty(const std::string& propertyId) {
interestedProperties.push_back(propertyId);
std::string msg = "Buyer " + id + " is interested in property " + propertyId;
send(msg, "allSellers");
}
};
// 具体同事类:卖家
class Seller : public Participant {
private:
std::unordered_map<std::string, std::string> properties;
public:
Seller(const std::string& sellerId, RealEstateMediator* m) : Participant(sellerId, m) {}
void send(const std::string& message, const std::string& targetId) override {
std::cout << "Seller " << id << " sends: " << message << " to " << targetId << std::endl;
mediator->sendMessage(message, id, targetId);
}
void receive(const std::string& message) override {
std::cout << "Seller " << id << " receives: " << message << std::endl;
}
void listProperty(const std::string& propertyId, const std::string& description) {
properties[propertyId] = description;
std::string msg = "Seller " + id + " listed property " + propertyId + ": " + description;
send(msg, "allBuyers");
}
void respondToInterest(const std::string& buyerId, const std::string& propertyId, const std::string& response) {
std::string msg = "Regarding property " + propertyId + ", seller " + id + " says: " + response;
send(msg, buyerId);
}
};
// 具体中介者:房产中介
class RealEstateAgent : public RealEstateMediator {
private:
std::unordered_map<std::string, Participant*> participants;
std::unordered_map<std::string, bool> verifiedInfo;
public:
void addParticipant(Participant* participant) override {
participants[participant->getId()] = participant;
verifiedInfo[participant->getId()] = false;
verifyInfo(participant->getId());
}
void sendMessage(const std::string& message, const std::string& senderId, const std::string& targetId) override {
if (targetId == "allBuyers") {
for (auto& pair : participants) {
if (dynamic_cast<Buyer*>(pair.second)) {
pair.second->receive(message);
}
}
}
else if (targetId == "allSellers") {
for (auto& pair : participants) {
if (dynamic_cast<Seller*>(pair.second)) {
pair.second->receive(message);
}
}
}
else if (participants.find(targetId) != participants.end()) {
participants[targetId]->receive(message);
}
}
void verifyInfo(const std::string& participantId) override {
std::cout << "Verifying information of participant " << participantId << std::endl;
// 模拟验证过程
verifiedInfo[participantId] = true;
std::cout << "Verification of participant " << participantId << " completed." << std::endl;
}
};
// 客户端代码
int main() {
RealEstateAgent* agent = new RealEstateAgent();
Buyer* buyer1 = new Buyer("B1", agent);
Buyer* buyer2 = new Buyer("B2", agent);
Seller* seller1 = new Seller("S1", agent);
Seller* seller2 = new Seller("S2", agent);
agent->addParticipant(buyer1);
agent->addParticipant(buyer2);
agent->addParticipant(seller1);
agent->addParticipant(seller2);
seller1->listProperty("P1", "A beautiful house near the park");
buyer1->showInterestInProperty("P1");
seller1->respondToInterest("B1", "P1", "The house is still available");
delete buyer1;
delete buyer2;
delete seller1;
delete seller2;
delete agent;
return 0;
}
状态模式
状态模式理论:
状态模式(State Pattern)是一种行为设计模式,它允许对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。该模式将状态封装成独立的类,并将动作委托给当前状态对象。当对象的内部状态发生变化时,其行为也会相应地发生变化,就好像对象所属的类被改变了一样。
状态模式的角色与结构
状态模式主要包含以下几个角色:
上下文(Context):定义客户端感兴趣的接口,并且维护一个具体状态类的实例,这个实例定义了当前的状态。上下文类会将与状态相关的操作委托给当前状态对象来处理。
抽象状态(State):定义一个接口以封装与上下文的一个特定状态相关的行为。抽象状态类通常包含多个抽象方法,这些方法对应着上下文对象在不同状态下可能执行的操作。
具体状态(Concrete State):实现抽象状态所定义的接口,每个具体状态类都实现了与特定状态相关的行为。当上下文的状态发生改变时,会切换到不同的具体状态类来处理相应的操作。
作者理解(大白话):
一个机器分为开启关闭和运型三种状态,然后在状态改变的时候,需要分别把这三个状态封装成三个类,然后在各个类(状态)里面进行操作,例如,在开启的状态下进行开关和运行的时候,就这样,以此类推没各类都有三个,一共9个,当然,在main函数里写的话,一定需要一个单独的类context进行链接,代码如下
#include <iostream>
#include <string>
// 前向声明
class Context;
// 抽象状态类
class State {
public:
virtual void openDoor(Context* context) = 0;
virtual void closeDoor(Context* context) = 0;
virtual void run(Context* context) = 0;
virtual void stop(Context* context) = 0;
virtual ~State() {}
};
// 上下文类
class Context {
private:
State* currentState;
public:
Context(State* state) : currentState(state) {}
void setState(State* state) {
currentState = state;
}
void openDoor() {
currentState->openDoor(this);
}
void closeDoor() {
currentState->closeDoor(this);
}
void run() {
currentState->run(this);
}
void stop() {
currentState->stop(this);
}
};
// 具体状态类:开门状态
class OpenDoorState : public State {
public:
void openDoor(Context* context) override {
std::cout << "The door is already open." << std::endl;
}
void closeDoor(Context* context) override {
std::cout << "Closing the door." << std::endl;
// 状态切换到关门状态
// 这里需要提前包含关门状态类的头文件,为简化示例省略
// context->setState(new CloseDoorState());
}
void run(Context* context) override {
std::cout << "Cannot run with the door open." << std::endl;
}
void stop(Context* context) override {
std::cout << "The elevator is already stopped with the door open." << std::endl;
}
};
// 具体状态类:关门状态
class CloseDoorState : public State {
public:
void openDoor(Context* context) override {
std::cout << "Opening the door." << std::endl;
// 状态切换到开门状态
// context->setState(new OpenDoorState());
}
void closeDoor(Context* context) override {
std::cout << "The door is already closed." << std::endl;
}
void run(Context* context) override {
std::cout << "Starting to run." << std::endl;
// 状态切换到运行状态
// context->setState(new RunState());
}
void stop(Context* context) override {
std::cout << "The elevator is already stopped with the door closed." << std::endl;
}
};
// 具体状态类:运行状态
class RunState : public State {
public:
void openDoor(Context* context) override {
std::cout << "Cannot open the door while the elevator is running." << std::endl;
}
void closeDoor(Context* context) override {
std::cout << "The door is already closed while running." << std::endl;
}
void run(Context* context) override {
std::cout << "The elevator is already running." << std::endl;
}
void stop(Context* context) override {
std::cout << "Stopping the elevator." << std::endl;
// 状态切换到停止状态
// context->setState(new StopState());
}
};
// 具体状态类:停止状态
class StopState : public State {
public:
void openDoor(Context* context) override {
std::cout << "Opening the door." << std::endl;
// 状态切换到开门状态
// context->setState(new OpenDoorState());
}
void closeDoor(Context* context) override {
std::cout << "The door is already closed." << std::endl;
}
void run(Context* context) override {
std::cout << "Starting to run." << std::endl;
// 状态切换到运行状态
// context->setState(new RunState());
}
void stop(Context* context) override {
std::cout << "The elevator is already stopped." << std::endl;
}
};
// 客户端代码
int main() {
State* openDoorState = new OpenDoorState();
Context* elevator = new Context(openDoorState);
elevator->openDoor();
elevator->closeDoor();
elevator->run();
elevator->stop();
delete elevator;
delete openDoorState;
return 0;
}
- 抽象状态类
State
:定义了电梯在不同状态下可能执行的操作,如开门、关门、运行和停止,这些操作都是纯虚函数,具体的实现由具体状态类完成。 - 上下文类
Context
:维护一个当前状态对象的指针currentState
,并提供了设置状态和执行操作的方法。在执行操作时,会将操作委托给当前状态对象来处理。 - 具体状态类(
OpenDoorState
、CloseDoorState
、RunState
、StopState
):实现了抽象状态类中定义的操作,每个具体状态类都有自己的行为逻辑。当执行某个操作时,可能会导致状态的切换,通过调用context->setState()
方法来实现。 - 客户端代码:创建了一个开门状态对象和一个电梯上下文对象,并调用电梯的各种操作方法,观察不同状态下的行为。
备忘录模式
备忘录模式理论:
备忘录模式(Memento Pattern)是一种行为设计模式,它允许在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。简单来说,就是在不暴露对象实现细节的情况下,保存和恢复对象的状态。
备忘录模式的角色与结构
备忘录模式主要包含以下三个角色:
原发器(Originator):需要保存状态的对象。原发器可以创建一个备忘录来保存其当前的内部状态,也可以使用备忘录来恢复其内部状态。
备忘录(Memento):用于存储原发器对象的内部状态。备忘录类通常提供了获取和设置状态的方法,但这些方法的访问权限需要根据具体情况进行控制,以保证状态的封装性。
管理者(Caretaker):负责保存备忘录,但不能对备忘录的内容进行操作或检查。管理者可以在需要的时候将备忘录交还给原发器,以便原发器恢复其状态。
作者理解(大白话):
在游戏中,我们经常需要保存角色的状态,以便在需要时恢复,比如玩家死亡后可以恢复到上一次存档的状态。
#include <iostream>
#include <string>
// 备忘录类
class CharacterMemento {
private:
int health;
int mana;
int level;
public:
CharacterMemento(int h, int m, int l) : health(h), mana(m), level(l) {}
int getHealth() const { return health; }
int getMana() const { return mana; }
int getLevel() const { return level; }
};
// 原发器类:游戏角色
class GameCharacter {
private:
int health;
int mana;
int level;
public:
GameCharacter(int h, int m, int l) : health(h), mana(m), level(l) {}
void takeDamage(int damage) {
health -= damage;
if (health < 0) health = 0;
}
void gainMana(int amount) {
mana += amount;
}
void levelUp() {
level++;
}
void displayStatus() const {
std::cout << "Health: " << health << ", Mana: " << mana << ", Level: " << level << std::endl;
}
// 创建备忘录
CharacterMemento createMemento() const {
return CharacterMemento(health, mana, level);
}
// 从备忘录恢复状态
void restoreFromMemento(const CharacterMemento& m) {
health = m.getHealth();
mana = m.getMana();
level = m.getLevel();
}
};
// 管理者类
class GameSaveManager {
private:
CharacterMemento* memento;
public:
GameSaveManager() : memento(nullptr) {}
~GameSaveManager() {
if (memento) delete memento;
}
void saveGame(const CharacterMemento& m) {
if (memento) delete memento;
memento = new CharacterMemento(m);
}
CharacterMemento getSave() const {
return *memento;
}
};
// 客户端代码
int main() {
GameCharacter character(100, 50, 1);
GameSaveManager saveManager;
std::cout << "Initial status: ";
character.displayStatus();
// 保存当前状态
saveManager.saveGame(character.createMemento());
// 角色受到伤害
character.takeDamage(30);
std::cout << "After taking damage: ";
character.displayStatus();
// 恢复到之前的状态
character.restoreFromMemento(saveManager.getSave());
std::cout << "Restored status: ";
character.displayStatus();
return 0;
}
组合模式
组合模式理论:
组合模式(Composite Pattern)是一种结构型设计模式,它允许你将对象组合成树形结构以表示 “部分 - 整体” 的层次关系。组合模式使得用户对单个对象和组合对象的使用具有一致性,也就是说,客户端代码可以统一处理单个对象和由多个对象组成的组合对象,而无需区分它们。
组合模式的角色与结构
组合模式主要包含以下几个角色:
抽象组件(Component):为组合中的对象声明接口,在抽象组件中可以定义一些通用的方法,如添加子组件、移除子组件、获取子组件等,同时也可以定义一些抽象方法,用于具体组件和组合组件实现。
叶子组件(Leaf):表示组合中的叶子节点对象,叶子节点没有子节点。叶子组件实现了抽象组件中定义的方法,但通常不包含添加、移除子组件等操作,因为它本身就是最底层的节点。
组合组件(Composite):表示组合中的分支节点对象,分支节点可以包含子节点,这些子节点可以是叶子节点,也可以是其他组合节点。组合组件实现了抽象组件中定义的所有方法,包括添加、移除子组件等操作,并且会递归地调用子组件的方法。
作者理解(大白话):
组合模式就是树形结构一样,比如一个游戏角色的技能,每个技能又会有子技能,那么当以后管理这些技能的时候,就构建一个树进行管理。其中精华的部分就是
void displayInfo() const override {
std::cout << "Skill Group: " << name << std::endl;
for (auto child : children) {
child->displayInfo();
}
}
这个代码很巧妙的进行了递归,当child是SkillGroup或者Skill的时候,分别可以进行对应类函数里的displayInfo,观察者模式的味道吧。
#include <iostream>
#include <vector>
#include <string>
// 抽象组件:技能树节点
class SkillTreeNode {
public:
virtual void displayInfo() const = 0;
virtual void add(SkillTreeNode* node) {}
virtual void remove(SkillTreeNode* node) {}
virtual ~SkillTreeNode() {}
};
// 叶子组件:技能
class Skill : public SkillTreeNode {
private:
std::string name;
std::string description;
public:
Skill(const std::string& n, const std::string& desc) : name(n), description(desc) {}
void displayInfo() const override {
std::cout << "Skill: " << name << std::endl;
std::cout << "Description: " << description << std::endl;
}
};
// 组合组件:技能组
class SkillGroup : public SkillTreeNode {
private:
std::string name;
std::vector<SkillTreeNode*> children;
public:
SkillGroup(const std::string& n) : name(n) {}
~SkillGroup() {
for (auto child : children) {
delete child;
}
}
void displayInfo() const override {
std::cout << "Skill Group: " << name << std::endl;
for (auto child : children) {
child->displayInfo();
}
}
void add(SkillTreeNode* node) override {
children.push_back(node);
}
void remove(SkillTreeNode* node) override {
for (auto it = children.begin(); it != children.end(); ++it) {
if (*it == node) {
delete* it;
children.erase(it);
break;
}
}
}
};
// 客户端代码
int main() {
// 创建技能和技能组
SkillGroup* rootSkillGroup = new SkillGroup("Root Skill Group");
SkillGroup* combatSkills = new SkillGroup("Combat Skills");
Skill* meleeAttack = new Skill("Melee Attack", "Basic melee attack skill");
Skill* rangedAttack = new Skill("Ranged Attack", "Shoot projectiles at enemies");
combatSkills->add(meleeAttack);
combatSkills->add(rangedAttack);
SkillGroup* magicSkills = new SkillGroup("Magic Skills");
Skill* fireBall = new Skill("Fire Ball", "Cast a fire ball at enemies");
Skill* iceShard = new Skill("Ice Shard", "Launch ice shards at enemies");
magicSkills->add(fireBall);
magicSkills->add(iceShard);
// 将子技能组添加到根技能组
rootSkillGroup->add(combatSkills);
rootSkillGroup->add(magicSkills);
// 显示整个技能树信息
rootSkillGroup->displayInfo();
// 清理内存
delete rootSkillGroup;
return 0;
}
-
抽象组件
SkillTreeNode
:- 定义了
displayInfo
纯虚函数,用于显示节点的信息。 - 提供了
add
和remove
方法的默认实现,用于添加和移除子节点。
- 定义了
-
叶子组件
Skill
:- 继承自
SkillTreeNode
,表示单个技能。 - 包含技能的名称和描述,实现了
displayInfo
方法来显示技能的详细信息。
- 继承自
-
组合组件
SkillGroup
:- 继承自
SkillTreeNode
,表示技能组,可以包含多个技能或子技能组。 - 包含一个
std::vector
来存储子节点,实现了displayInfo
方法,会递归调用子节点的displayInfo
方法来显示整个技能组的信息。 - 实现了
add
和remove
方法,用于添加和移除子节点。
- 继承自
-
客户端代码:
- 创建了根技能组、战斗技能组、魔法技能组以及各种具体技能。
- 将具体技能添加到相应的技能组中,再将子技能组添加到根技能组中。
- 调用根技能组的
displayInfo
方法来显示整个技能树的信息。 - 最后释放根技能组的内存,由于在
SkillGroup
的析构函数中会递归释放子节点的内存,所以整个技能树的内存都会被正确释放。
迭代器模式
一步理解:
1. 场景引入
想象你有一个装满各种零食的大箱子,这个箱子就是一个集合,里面装了好多零食对象。现在你想要挨个看看箱子里都有啥零食,但是你又不想把箱子打开后随便乱翻,希望能有一个有顺序、有规矩的方式去查看每一个零食。迭代器模式就能帮你实现这个需求。
2. 各个角色对应
抽象迭代器:就好比是一个查看零食的规则说明。它规定了查看零食的基本操作,比如能不能继续看下一个零食(类似迭代器里的 hasNext
方法),以及怎么拿出下一个零食(类似迭代器里的 next
方法)。这个规则说明是通用的,不管箱子里装的是薯片、巧克力还是糖果,都按照这个规则来查看。
具体迭代器:这就像是一个按照规则去实际查看零食的人。他手里拿着前面说的规则说明,在箱子里一个一个地查看零食。当你让他拿出下一个零食时,他就按照规则从箱子里取出一个;当你问他还有没有下一个零食时,他也能根据规则判断出来。在 C++ 里,具体迭代器会实现抽象迭代器规定的那些方法,来完成对集合元素的遍历。
抽象聚合:可以把它想象成装零食箱子的设计蓝图。这个蓝图规定了箱子应该具备的一些功能,比如得能创建一个查看零食的人(对应迭代器模式里的创建迭代器),还得能知道箱子里有多少零食(对应获取集合大小),以及能根据位置拿出特定的零食(对应根据索引获取元素)。
具体聚合:这就是实际的那个装零食的箱子。它按照前面的设计蓝图制作出来,并且实现了蓝图里规定的功能。它能创建出一个查看零食的人(也就是创建具体迭代器),能告诉你箱子里有多少零食,还能让你根据位置拿出特定的零食。
3. 工作流程
当你想要查看箱子里的零食时,你先找到这个装零食的箱子(具体聚合),然后让箱子给你安排一个查看零食的人(调用具体聚合的创建迭代器方法得到具体迭代器)。接着,你就可以让这个查看零食的人按照规则一个一个地把零食拿给你看。他每次拿出一个零食之前,会先看看箱子里还有没有下一个零食(调用 hasNext
方法判断),如果有,就把下一个零食拿给你(调用 next
方法),直到箱子里没有零食可看为止。
#include <iostream>
// 抽象迭代器,相当于查看零食的规则说明
template <typename T>
class Iterator {
public:
// 判断是否还有下一个零食
virtual bool hasNext() const = 0;
// 拿出下一个零食
virtual T next() = 0;
virtual ~Iterator() {}
};
// 抽象聚合,相当于装零食箱子的设计蓝图
template <typename T>
class Aggregate {
public:
// 创建一个查看零食的人
virtual Iterator<T>* createIterator() const = 0;
// 知道箱子里有多少零食
virtual int size() const = 0;
// 根据位置拿出特定的零食
virtual T get(int index) const = 0;
virtual ~Aggregate() {}
};
// 具体迭代器,相当于实际查看零食的人
template <typename T>
class ArrayIterator : public Iterator<T> {
private:
const Aggregate<T>* aggregate; // 拿着箱子
int index; // 当前看到第几个零食了
public:
ArrayIterator(const Aggregate<T>* agg) : aggregate(agg), index(0) {}
bool hasNext() const override {
// 判断是否还有下一个零食
return index < aggregate->size();
}
T next() override {
// 拿出下一个零食并更新位置
return aggregate->get(index++);
}
};
// 具体聚合,相当于实际的装零食箱子
template <typename T, int N>
class ArrayAggregate : public Aggregate<T> {
private:
T array[N]; // 装零食的地方
public:
ArrayAggregate(const T (&arr)[N]) {
for (int i = 0; i < N; ++i) {
array[i] = arr[i]; // 把零食放进箱子
}
}
Iterator<T>* createIterator() const override {
// 创建一个查看零食的人
return new ArrayIterator<T>(this);
}
int size() const override {
// 知道箱子里有多少零食
return N;
}
T get(int index) const override {
// 根据位置拿出特定的零食
return array[index];
}
~ArrayAggregate() {
// 迭代器在外部创建,需要外部手动释放
}
};
// 客户端代码,就像是你去查看零食
int main() {
int arr[] = {1, 2, 3, 4, 5}; // 这是一堆零食
ArrayAggregate<int, 5> aggregate(arr); // 把零食装进箱子
Iterator<int>* iterator = aggregate.createIterator(); // 让箱子安排一个查看零食的人
while (iterator->hasNext()) {
// 只要还有下一个零食,就拿出来看看
std::cout << iterator->next() << " ";
}
std::cout << std::endl;
delete iterator; // 看完了,释放查看零食的人
return 0;
}
在这个代码里,Iterator
就是抽象迭代器,规定了查看元素的规则;ArrayIterator
是具体迭代器,按照规则去遍历元素;Aggregate
是抽象聚合,定义了集合的基本功能;ArrayAggregate
是具体聚合,实现了这些功能并存储元素。在 main
函数里,就相当于你拿着箱子,让箱子安排人去查看里面的元素,最后输出了箱子里的所有元素。