文章目录
- 设计模式
- 创建型
- *工厂模式
- *抽象工厂
- 生成器
- 原型
- *单例
- 结构型
- 适配器
- 桥接
- *组合
- 装饰
- 外观
- 享元
- *代理
- 行为型
- 责任链
- *命令
- 迭代器
- 中介者
- 备忘录
- 观察者
- 状态
- *策略
- 模板方法
- 访问者
- MVC
设计模式
创建型
*工厂模式
属于类创建型
问题背景:一个物流公司,最开始设计的是一个卡车路线,现在要拓展业务,开辟一个水路路线,考虑未来可能还会拓展更多的业务,这里就需要用到工厂模式。工厂模式的核心是:把new关起来,实现创造者和产品的松耦合
代码实例
#include <iostream>//产品的接口
class Transport {
public:virtual ~Transport() {};virtual void deliver() const = 0; //纯虚函数
};//产品a
class Truck : public Transport {
public:void deliver() const override {std::cout << "卡车运输货物中...\n";}
};//产品b
class Ship : public Transport {
public:void deliver() const override {std::cout << "轮船运输货物中...\n";}
};//创造者
class Logistics {
public:virtual ~Logistics() {};//工厂方法的核心virtual Transport* factoryMethod() const = 0;//接口 通常都是publicvoid doSomething() const {//父类指针或引用指向子类对象Transport* transport = factoryMethod();transport->deliver();delete transport;}
};//具体创造者a
class TruckLogistics : public Logistics {~TruckLogistics() {};virtual Transport* factoryMethod() const override {return new Truck();}
};//具体创造者b
class ShipLogistics : public Logistics {~ShipLogistics() {};virtual Transport* factoryMethod() const override {return new Ship();}
};int main() {//卡车Logistics* truckLogistics = new TruckLogistics();truckLogistics->doSomething();//轮船Logistics* shipLogistics = new ShipLogistics();shipLogistics->doSomething();delete truckLogistics;delete shipLogistics;return 0;
}
总结成几个字:面向接口编程、当有新需求的时候只需要创建一个新的类即可
缺点:是针对类的一个改造方法,该方法需要引入许多新的子类,代码可能会因此变得复杂,举个例子,假如有12种颜色和12种形状,那么就有12*12=144个类,这会使得代码十分臃肿
*抽象工厂
属于对象创建型
问题背景:家具店里有椅子、桌子等产品,产品有不同风格,如现代、北欧、工业等等。希望确保客户收到的产品风格统一
#include <iostream>class Chair {
public:virtual ~Chair() {};virtual void sitOn() const = 0;
};class ModernChair : public Chair {
public:virtual ~ModernChair() {};virtual void sitOn() const override {std::cout << "可以被坐下的ModernChair\n";}
};class ChineseChair : public Chair {
public:virtual ~ChineseChair() {};virtual void sitOn() const override {std::cout << "可以被坐下的ChineseChair\n";}
};class Table {
public:virtual ~Table() {};virtual void putOn() const = 0;
};class ModernTable : public Table {
public:virtual ~ModernTable() {};virtual void putOn() const override {std::cout << "可以放东西的ModernChair\n";}
};class ChineseTable : public Table {
public:virtual ~ChineseTable() {};virtual void putOn() const override {std::cout << "可以放东西的ChineseChair\n";}
};//抽象工厂
class FurnitureFactory {
public:virtual Chair* createChair() const = 0;virtual Table* createTable() const = 0;
};class ModernStyleFactory : public FurnitureFactory {
public:virtual Chair* createChair() const override {return new ModernChair();}virtual Table* createTable() const override {return new ModernTable();}
};class Client {
private:FurnitureFactory* m_factory;
public:Client(FurnitureFactory* factory) {m_factory = factory;}void buyFurniture() {Chair* chair = m_factory->createChair();;Table* table = m_factory->createTable();;chair->sitOn();table->putOn();delete chair;delete table;}
};int main() {//创建一个只含modern类型的桌椅ModernStyleFactory modernFactory;Client client(&modernFactory);client.buyFurniture();return 0;
}
生成器
属于对象创建型
将一个复杂对象的构建与它的表示分离
#include <iostream>
#include <vector>
#include <string>class SimpleHouse {
public:std::vector<std::string> m_parts;void printParts() const {std::cout << "SimpleHouse包括:\n";for (auto& part : m_parts) {std::cout << part << "\n";}std::cout << "---------------\n";}
};class Builder {
public://接口通常都写上虚析构virtual ~Builder() {};virtual void reset() = 0;virtual void makeBaseHouse() = 0;virtual void makeGarage() = 0;virtual void makePool() = 0;
};class SimpleHouseBuilder : public Builder {
private:SimpleHouse* m_simplehouse;public:SimpleHouseBuilder() {reset();}~SimpleHouseBuilder() {delete m_simplehouse;}void reset() override {m_simplehouse = new SimpleHouse();}virtual void makeBaseHouse() override {m_simplehouse->m_parts.emplace_back("BaseHouse");}virtual void makeGarage() override {m_simplehouse->m_parts.emplace_back("Garage");}virtual void makePool() override {m_simplehouse->m_parts.emplace_back("Pool");}SimpleHouse* getResult() {SimpleHouse* result = m_simplehouse;reset(); //重新初始化m_simplehousereturn result;}
};class Director {
private:Builder* m_builder;public:void setBuilder(Builder* builder) {m_builder = builder;}void makeSimpleHouse() {m_builder->makeBaseHouse();m_builder->makeGarage();}void makeFullFuncHouse() {m_builder->makeBaseHouse();m_builder->makeGarage();m_builder->makePool();}
};void client(Director* director) {std::cout << "客户自己设计流程:\n";SimpleHouseBuilder* builder = new SimpleHouseBuilder();builder->makeBaseHouse();builder->makeGarage();SimpleHouse* simpleHouse = builder->getResult();simpleHouse->printParts();//delete simpleHouse;std::cout << "\n主管自己设计流程:\n";director->setBuilder(builder);director->makeFullFuncHouse();simpleHouse = builder->getResult();simpleHouse->printParts();delete simpleHouse;delete builder;
}int main() {Director director;client(&director);return 0;
}
我觉得代码的reset()
函数很巧妙
原型
属于对象创建型
#include <iostream>
#include <unordered_map>
#include <string>using std::string;enum Type {ROBOT_CAT = 0,ROBOT_DOG
};class Robot {
protected:string m_prototype_name = "";float m_stateOfCharge = 0;public:Robot() = default;Robot(string name) : m_prototype_name(name) {}virtual ~Robot() {}virtual Robot* clone() const = 0;virtual void setStateOfCharge(float) = 0;
};class RobotCat : public Robot {
private:float m_CatValue = 0;
public:virtual ~RobotCat() {}RobotCat(const RobotCat& robot) {m_CatValue = robot.m_CatValue;}RobotCat(string name, float value) : Robot(name), m_CatValue(value) {}virtual Robot* clone() const override {return new RobotCat(*this);}virtual void setStateOfCharge(float value) override {m_stateOfCharge = value;std::cout << "---" << m_prototype_name << "当前电量:" << m_stateOfCharge << ", m_CatValue:" << m_CatValue << "\n";}
};class RobotDog : public Robot {
private:float m_DogValue = 0;
public:virtual ~RobotDog() {}RobotDog(string name, float value) : Robot(name), m_DogValue(value) {}virtual Robot* clone() const override {return new RobotDog(*this);}virtual void setStateOfCharge(float value) override {m_stateOfCharge = value;std::cout << "---" << m_prototype_name << "当前电量:" << m_stateOfCharge << ", m_DogValue:" << m_DogValue << "\n";}
};class CloneFactory {std::unordered_map<Type, Robot*> m_prototypes;
public:CloneFactory() {m_prototypes[ROBOT_CAT] = new RobotCat("机器猫", 5.0);m_prototypes[ROBOT_DOG] = new RobotDog("机器狗", 8.0);}~CloneFactory() {delete m_prototypes[ROBOT_CAT];delete m_prototypes[ROBOT_DOG];}Robot* createRobot(Type type) {return m_prototypes[type]->clone();}
};void clientCode(CloneFactory& cloneFactory) {std::cout << "克隆机器猫:\n";Robot* cloneRobot = cloneFactory.createRobot(ROBOT_CAT);cloneRobot->setStateOfCharge(90);delete cloneRobot;cloneRobot = cloneFactory.createRobot(ROBOT_CAT);cloneRobot->setStateOfCharge(80);delete cloneRobot;std::cout << "克隆机器狗:\n";cloneRobot = cloneFactory.createRobot(ROBOT_DOG);cloneRobot->setStateOfCharge(75);delete cloneRobot;
}int main() {CloneFactory cloneFactory;clientCode(cloneFactory);return 0;
}
*单例
属于对象创建型
问题背景:对于某些类来说,只有一个实例是很重要的,比如数据库或日志类
#include <iostream>
#include <thread>
#include <mutex>class SingleTon {
private:SingleTon(const std::string value) : m_value(value){}~SingleTon() {}std::string m_value;public:SingleTon(SingleTon& other) = delete;SingleTon(const SingleTon& other) = delete;void operator=(const SingleTon&) = delete;std::string getValue() const { return m_value; }static SingleTon* getInstance(const std::string& value);private:static SingleTon* m_instance;static std::mutex m_mutex;
};//静态成员变量在类外初始化需要带上返回值
SingleTon* SingleTon::m_instance = nullptr;
std::mutex SingleTon::m_mutex;SingleTon* SingleTon::getInstance(const std::string& value) {//加锁的方法在线程量大的时候很占资源//std::unique_lock<std::mutex> lock(m_mutex);//if (m_instance == nullptr) {// m_instance = new SingleTon(value);//}//return m_instance;//双检查 但是编译器优化会跳过第一个检查 所以这样写不是线程安全的//if (m_instance == nullptr) {// std::unique_lock<std::mutex> lock(m_mutex);// if (m_instance == nullptr) {// m_instance = new SingleTon(value);// }// return m_instance;//}//初始化的时候是线程安全的---C11 静态变量只会初始化一次//static SingleTon* instance = new SingleTon(value);//return instance;static SingleTon instance(value);return &instance;
}void Cat() {SingleTon* singleton = SingleTon::getInstance("cat");std::cout << singleton->getValue() << "\n";
}void Dog() {SingleTon* singleton = SingleTon::getInstance("Dog");std::cout << singleton->getValue() << "\n";
}int main() {//Cat();//Dog();//只有输出都是cat或者都是dog才是对的 线程的执行先后是不确定的 只要保证是单例就表明这个demo是对的std::thread t1(&Cat);std::thread t2(&Dog);t1.join();t2.join();return 0;
}
最优的解决办法就是用初始化静态变量的方法(这个变量的类型是只能创建一个单例的类的类型),因为静态变量只能初始化一次,并且在C11中初始化是线程安全的。也可以通过加锁的形式来解决,只不过在考虑线程量大的时候加锁的方式太占用资源了。
结构型
适配器
实例属于对象结构型
问题背景:方钉和圆孔问题,将xml格式的数据放到分析函数中,但是分析函数只能兼容json格式的数据。需要让客户。解决方法可以理解成将一个类型包装起来,让程序看上去好像是按照自己的情况运行的
#include <iostream>//Target:客户端需要的目标接口
class JsonInfo {
public:virtual ~JsonInfo() {}virtual std::string request() const {return "Some Json information......\n";}//有virtual ... = 0;的函数才是纯虚函数 这样的类才是抽象类 不能被实例化//virtual void func() const = 0;
};//Adaptee:客户端不兼容的接口,需要转化成Target接口
class XmlInfo {
public:virtual std::string specialRequest() const {return "Some Xml information......\n";}
};//Adaptor:适配器,就是把Adaptee包装起来,让他看上去像是Target
class XmlJsonAdaptor : public JsonInfo {
private:XmlInfo* m_adaptee;
public:XmlJsonAdaptor(XmlInfo* adaptee) : m_adaptee(adaptee) {}virtual std::string request() const override {std::string s = m_adaptee->specialRequest();return "Json<-XmlJsonAdaptor<-"+s;}
};void clientCode(const JsonInfo* info) {std::cout << "股票分析软件运行Json:" << info->request() << "\n";std::cout << "------------------------------------\n";
}int main() {JsonInfo jsonInfo;clientCode(&jsonInfo);XmlInfo xmlInfo;XmlJsonAdaptor jsonadaptor(&xmlInfo);clientCode(&jsonadaptor); //需要解决的问题return 0;
}
关键是要学会它们是怎么关联起来的
桥接
对象结构型
问题背景:遥控器和设备属于同一个商品的部分,设备之间基本上有共同的特点,如开机、关机等等…可以将这些共性写在一个桥梁类中,然后根据不同的设备构造不同的遥控器以满足遥控器的功能和设备对应
#include <iostream>
#include <string>using std::string;//实现
class Device {
public:virtual ~Device() {}virtual string turnOn() const = 0;virtual string turnOff() const = 0;virtual string mute() const = 0;
};class TV : public Device {
public:~TV() {}string turnOn() const override {return "TV:开机...\n";}string turnOff() const override {return "TV:关机...\n";}string mute() const override {return "TV:静音...\n";}
};class Radio : public Device {
public:~Radio() {}//纯虚函数一定要重写 不重写的子类任然是抽象类string turnOn() const override {return "Radio:开机...\n";}string turnOff() const override {return "Radio:关机...\n";}string mute() const override {return "Radio:静音...\n";}
};//抽象桥梁
class BaseRemoteController {
protected:Device* m_implementation;public:~BaseRemoteController() {}BaseRemoteController(Device* implementation) : m_implementation(implementation) {}virtual string sendTurnOn() {return "基础遥控器发出TurnOn:" + m_implementation->turnOn();}virtual string sendTurnOff() {return "基础遥控器发出TurnOff:" + m_implementation->turnOff();}};class AdvancedRemoteController : public BaseRemoteController {
public://初始化列表直接调用父类的构造函数AdvancedRemoteController(Device* implementation) : BaseRemoteController(implementation) {}virtual string sendTurnOn() override {return "高级遥控器发出TurnOn:" + m_implementation->turnOn();}virtual string sendTurnOff() override {return "高级遥控器发出TurnOff:" + m_implementation->turnOff();}string sendMute() {return "高级遥控器发出Mute:" + this->m_implementation->mute();}
};int main() {TV tv;BaseRemoteController brc(&tv);//std::cout << brc.sendMute(); //基础遥控器没有mute功能std::cout << brc.sendTurnOff();std::cout << brc.sendTurnOn();Radio radio;AdvancedRemoteController abrc(&radio);std::cout << abrc.sendMute();std::cout << abrc.sendTurnOff();std::cout << abrc.sendTurnOn();return 0;
}
*组合
对象结构型
问题背景:复杂的订单计算,有两类对象:产品和盒子,一个盒子中可以包含多个产品或多个盒子,解决问题的算法通常是递归
#include <iostream>
#include <string>
#include <list>using std::string;//接口:不管是商品还是盒子,都依赖这个接口
class OrderNode {
protected:OrderNode* m_parent;float m_price;public:virtual ~OrderNode() {}OrderNode() : m_parent(nullptr), m_price(0.0) {}OrderNode(OrderNode* parent, float price) : m_parent(parent), m_price(price) {}void setParent(OrderNode* node) {m_parent = node;}OrderNode* getParent() {return m_parent;}void setPrice(float price) {m_price = price;}float getPrice() {return m_price;}virtual bool isLeaf() const {return false;}virtual std::string Operation() = 0;};//产品
class Product : public OrderNode {
public:~Product() {}Product(float price) : OrderNode(nullptr, price) {}virtual std::string Operation() override {return "产品";}
};//盒子
class Box : public OrderNode {
protected:std::list<OrderNode*> m_children;
public:~Box() {}Box() {}bool isLeaf() const override {return true;}void Add(OrderNode* node) {m_children.push_back(node);node->setParent(this);m_price += node->getPrice();}void Remove(OrderNode* node) {m_children.remove(node); //只是从容器中移除 要考虑回收内存node->setParent(nullptr);m_price -= node->getPrice();}virtual std::string Operation() override {std::string res;m_price = 0;for (auto c : m_children) {if (c == m_children.back()) {res += c->Operation();}else {res += c->Operation() + "+";}m_price += c->getPrice();}return "盒子(" + res + ")";}
};void clientCode(OrderNode* node) {std::cout << "结构:" << node->Operation() << "\n";std::cout << "价格:" << node->getPrice();
}int main() {std::cout << "处理叶子节点...\n";Product simple(5.0);clientCode(&simple);std::cout << "\n\n";std::cout << "处理组合节点...\n";Box tree;Box branch1;Box branch2;Product leaf1(5.0);Product leaf2(5.0);Product leaf3(5.0);tree.Add(&branch1);tree.Add(&branch2);branch1.Add(&leaf1);branch1.Add(&leaf2);branch2.Add(&leaf3);clientCode(&tree);return 0;
}
装饰
对象结构型
问题背景:饮料店订单系统,饮料多种,可以选择加各种配料
- 继承:静态
- 多态:动态
#include <iostream>
#include <string>using std::string;//接口:具体被包裹的类,以及装饰类
class Beverage {
public:virtual ~Beverage() {}virtual string Operation() const = 0;
};class Americano : public Beverage {
public:~Americano() {}virtual string Operation() const override {return "美式咖啡";}
};//装饰
//基础部分(可能包括额外部分)
class Ingredient : public Beverage {
protected:Beverage* m_beverage;public:~Ingredient() {}Ingredient(Beverage* beverage) : m_beverage(beverage) {}virtual string Operation() const override {//核心代码 不是用来被基类覆盖的return m_beverage->Operation();}
};//额外部分(需要委托基类,完成基础部分)
class Whip : public Ingredient {
public:~Whip() {}Whip(Beverage* beverage) : Ingredient(beverage) {}virtual string Operation() const override {//在基类的operation之前,之后都可以额外增加操作return "奶昔(" + Ingredient::Operation() + ")";}
};class Moca : public Ingredient {
public:~Moca() {}Moca(Beverage* beverage) : Ingredient(beverage) {}virtual string Operation() const override {//在基类的operation之后都可以额外增加操作return "摩卡(" + Ingredient::Operation() + ")";}
};void clientCode(Beverage* bvag) {std::cout << "执行结果:" << bvag->Operation() << "\n";
}int main() {Beverage* ano = new Americano;std::cout << "普通美式咖啡:\n";clientCode(ano);Beverage* whip = new Whip(ano); //往ano中加入whipBeverage* moca1 = new Moca(whip); //往whip1中加moca1Beverage* moca2 = new Moca(moca1); //往moca1中加moca2std::cout << "奶昔+双份摩卡美式咖啡:\n";clientCode(moca2);return 0;
}
有点像套娃的感觉。缺点构建对象的时候是一个栈的结构,在删除特定封装器的时候比较困难
外观
对象结构型
问题背景:有一套复杂的视频系统以及音频系统,提供简洁的操作面板。主要是针对用户体验
#include <iostream>
#include <string>using std::string;class VideoStream {
public:string initial() const {return "视频系统:Ready!\n";}string play() const {return "视频系统:Go!\n";}string operationX() const {return "视频系统:不常用!\n";}
};class RadioStream {
public:string initial() const {return "音频系统:Ready!\n";}string play() const {return "视频系统:Go!\n";}string operationX() const {return "视频系统:不常用!\n";}
};class Controller {
protected:VideoStream* m_video;RadioStream* m_radeo;public:Controller(VideoStream* video = nullptr, RadioStream* radio = nullptr) {if (!video) m_video = video;else m_video = new VideoStream;m_radeo = radio ? radio : new RadioStream;}~Controller() {delete m_video;delete m_radeo;}string start() {string s = "控制器启动系统:\n";s += m_video->initial();s += m_radeo->initial();s += "控制器播放\n";s += m_video->play();s += m_radeo->play();return s;}
};int main() {VideoStream* v = new VideoStream;RadioStream* r = new RadioStream;Controller con(v, r);std::cout << con.start();return 0;
}
这个相对简单,都没用到继承和多态
享元
对象结构型
问题背景:做一个车管所系统,会产生大量车辆实体,如果每一个实体都要保存信息,将会需要大量内存。
用到的比较少,这种一般通过数据库方面解决的
*代理
对象结构型
问题背景:系统需要访问数据库,但需要对数据的访问做优化,例如缓存查询结果、生成访问日志、访问控制\
#include <iostream>
#include <string>using std::string;//接口:数据库和代理数据库都依赖这个接口
class DataBase {
public:virtual void request() const = 0;
};class RealDataBase : public DataBase {
public:virtual void request() const override {std::cout << "真实数据库:处理业务请求。\n";}
};class ProxyDataBase : public DataBase {
private:RealDataBase* m_realDataBase;bool checkAccess() const {std::cout << "ProxyDataBase:在发出请求之前,检查一下。\n";return true;}void log() const {std::cout << "ProxyDataBase:处理日志。\n";}public:ProxyDataBase(RealDataBase* realDataBase) : m_realDataBase(realDataBase) {}virtual void request() const override {if (this->checkAccess()) {std::cout << "ProxyDataBase:通过代理处理数据库请求。\n";}else {std::cout << "ProxyDataBase:数据库访问请求被驳回。\n";}this->log();}
};//这是传入的引用...
void client(const DataBase& database) {database.request();
}int main() {RealDataBase rdb;ProxyDataBase pdb(&rdb);client(pdb);return 0;
}
为其它对象提供一种代理以控制这个对象的访问。即新建一个与原服务器对象接口相同的代理类,代理将自己伪装成数据库对象,对客户而言是透明的
行为型
责任链
对象行为型
问题背景:故障报修系统,不同业务员处理的故障不同,如何确保客户的维护请求得到妥善处理。比如打电话找人维修,可能先是机器人服务,如果没能解决就是人工服务,再没解决就是上门服务…
#include <iostream>
#include <string>
#include <list>using std::string;class BaseHandler {
private:BaseHandler* m_nexthandler = nullptr;
public://set函数有返回值 很少见 可以联想输出运算符<<BaseHandler* setNext(BaseHandler* handler) {m_nexthandler = handler;return m_nexthandler;}virtual string handle(std::string request) {if (m_nexthandler) {return m_nexthandler->handle(request);}return "";}
};class RobotAI : public BaseHandler {
public:virtual string handle(std::string request) override {if (request == "使用向导") {return "RobotAI:我来处理-" + request + "-。\n";}else {return BaseHandler::handle(request);}}
};class TelOperator : public BaseHandler {
public:virtual string handle(std::string request) override {if (request == "常见问题") {return "TelOperator:我来处理-" + request + "-。\n";}else {return BaseHandler::handle(request);}}
};class Expert : public BaseHandler {
public:virtual string handle(std::string request) override {if (request == "疑难杂症") {return "Expert:我来处理-" + request + "-。\n";}else {return BaseHandler::handle(request);}}
};void client(BaseHandler& bh) {std::list<string> problems = { "使用向导", "常见问题", "疑难杂症" , "666的问题", "使用向导", "疑难杂症"};for (const std::string& problem : problems) {std::string res = bh.handle(problem);if (res.empty()) {std::cout << "处理不了\n";}else {std::cout << "处理结果:" << res << "\n";}}
}int main() {RobotAI robot;TelOperator tel;Expert expert;robot.setNext(&tel)->setNext(&expert);std::cout << "Chain:robot->话务员->专家\n";client(robot);return 0;
}
*命令
对象行为型
问题背景:模拟小餐馆点餐,客户提交订单给服务员,服务员将需求提交给大厨,由大厨完成食物的准备工作
#include <iostream>
#include <string>
#include <vector>//Receiver
class Kitchen {
private:Kitchen() {}public://单例模式static Kitchen* getInstance() {static Kitchen* instance = new Kitchen();return instance;}void prepareFood(const std::string& food) {std::cout << "厨房:正在准备(" << food << ")\n";}
};class Command {
public:virtual ~Command() {}virtual void execute() const = 0;
};class Order : public Command {
private:Kitchen* m_kitchen;std::vector<std::string> m_foods;public:Order(Kitchen* kitchen, std::vector<std::string> foods) : m_kitchen(kitchen), m_foods(foods) {}virtual ~Order() {}virtual void execute() const override {std::cout << "订单:需要厨房进行处理...\n";for (const std::string& item : m_foods) {m_kitchen->prepareFood(item);}}
};//Invoker
class Waiter {
private:Command* m_command;public:~Waiter() { delete m_command; }void orderUp(Command* command) {std::cout << "服务员:...提交订单...\n";m_command = command;m_command->execute();}
};class Client {
public:void orderFood(Waiter& waitress, std::vector<std::string> foods) {waitress.orderUp(new Order(Kitchen::getInstance(), foods));}
};int main() {Client c;Waiter w;c.orderFood(w, { "波士顿大龙虾", "刀削", "咖啡" });return 0;
}
将请求封装为一个对象,从而可用不同的请求对客户进行参数化
迭代器
对象行为性
问题背景:两个餐厅要合并,虽然两家菜单系统类似,但底层使用的数据结构不同,如何能让客户端方便的遍历
中介者
对象行为型
问题背景:实现一个机场的起飞管理系统,如果由驾驶员们讨论谁先飞,后果可能是灾难性的
#include <iostream>
#include <string>class Staff;//meidator interface
class ControlTower {
public:virtual void notify(Staff* sender, std::string event) const = 0;
};class Staff {
protected:ControlTower* m_controlTower;std::string m_name;public:Staff(std::string name, ControlTower* controlTower = nullptr) : m_controlTower(controlTower), m_name(name) {}std::string getName() { return m_name; }void setMediator(ControlTower* controlTower) {m_controlTower = controlTower;}};class Pilot : public Staff {
public:Pilot(std::string name) : Staff(name) {}void takeOff() {std::cout << this->getName() + ":请求起飞。\n";m_controlTower->notify(this, "请求起飞");}void copy() {std::cout << this->getName() + ":收到。\n";}
};class GroundGrew : public Staff {
public:GroundGrew(std::string name) : Staff(name) {}void maintaince() {std::cout << this->getName() + ":请求维护。\n";m_controlTower->notify(this, "请求维护");}void copy() {std::cout << this->getName() + ":收到。\n";}
};class ConcreteControlTower : public ControlTower {
private:Pilot* m_p1;Pilot* m_p2;Pilot* m_p3;GroundGrew* m_g;public:ConcreteControlTower(Pilot* p1, Pilot* p2, Pilot* p3, GroundGrew* g) : m_p1(p1), m_p2(p2), m_p3(p3), m_g(g) {m_p1->setMediator(this);m_p2->setMediator(this);m_p3->setMediator(this);m_g->setMediator(this);}virtual void notify(Staff* sender, std::string event) const override {std::cout << "控制塔:收到" + sender->getName() + event + "\n";if (event == "请求起飞") {m_g->copy();if (sender != m_p1) m_p1->copy();if (sender != m_p2) m_p2->copy();if (sender != m_p3) m_p3->copy();}if (event == "请求维护") {m_p1->copy();m_p2->copy();m_p3->copy();}}
};int main() {Pilot* p1 = new Pilot("空军1号");Pilot* p2 = new Pilot("空军2号");Pilot* p3 = new Pilot("空军3号");GroundGrew* g1 = new GroundGrew("地勤1");ConcreteControlTower* ct = new ConcreteControlTower(p1, p2, p3, g1);p1->takeOff();g1->maintaince();delete p1;delete p2;delete p3;delete g1;return 0;
}
用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显示地相互引用,从而是得其耦合松散
备忘录
对象行为型
问题背景:实现一个游戏的存档功能,希望在保存状态的同时可以不破坏类的封装
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string>
#include <vector>
#include <ctime>//memento 一定得写在Hero类之前
class Memento {friend class Hero; //将类Hero设置成友元
private:unsigned int m_state;std::string m_date;public:Memento(unsigned int state) : m_state(state) {std::time_t now = std::time(0);m_date = std::ctime(&now);}std::string getDate() {return m_date;}
};//Originator
class Hero {
private: unsigned int m_state;public:Hero(unsigned int state) : m_state(state) {std::cout << "英雄:我的初始状态为:" << m_state << "\n";}void fight() {std::cout << "英雄:啊!被坎了一刀。\n";m_state -= rand() % 20; //0-19std::cout << "英雄:当前状态变为:" << m_state << "\n";}Memento* save() {return new Memento(m_state);}void restore(Memento* memento) {m_state = memento->m_state;std::cout << "英雄:当前状态恢复为:" << m_state << "\n";}
};//caretaker
class Caretaker {
private:Hero* m_hero;std::vector<Memento*> m_memetos;public:Caretaker(Hero* hero) : m_hero(hero) {}~Caretaker() {for (auto& item : m_memetos) delete item;}void backup() {std::cout << "管理者:正在保存英雄状态" << "\n";m_memetos.push_back(m_hero->save());}void undo() {if (!m_memetos.size()) return;Memento* m = m_memetos.back();m_memetos.pop_back();std::cout << "管理者:英雄状态恢复为" << m->getDate() << "\n";m_hero->restore(m);delete m;}
};int main() {//根据时间生成随机数的种子std::srand(static_cast<unsigned int>(std::time(NULL)));Hero* hero = new Hero(100);Caretaker* caretaker = new Caretaker(hero);caretaker->backup();hero->fight();caretaker->backup();hero->fight();caretaker->undo();return 0;
}
观察者
对象行为型
问题背景:开发一个购物平台,商品缺货的时候如何处理?客户主动询问会浪费客户的时间。平台主动发送通知给所有客户的话对一些不需要的客户不友好。
#include <iostream>
#include <string>
#include <list>class IObserver {
public:virtual void update(const std::string& message) = 0;
};class ISubject {
public:virtual void attach(IObserver* observer) = 0;virtual void detach(IObserver* observer) = 0;virtual void notify() = 0;
};class Mate50 : public ISubject {
private:std::list<IObserver*> m_observerList;std::string m_message;public:virtual void attach(IObserver* observer) override {m_observerList.push_back(observer);}virtual void detach(IObserver* observer) override {m_observerList.remove(observer);}virtual void notify() override {std::list<IObserver*>::iterator it = m_observerList.begin();while (it != m_observerList.end()) {(*it++)->update(m_message);}}void createMessage(std::string message = "") {m_message = message;notify();}
};class Customser : public IObserver {
private:ISubject* m_mate50;std::string m_message;int m_number;static int m_sNum;public:Customser(ISubject* subject) : m_mate50(subject) {m_mate50->attach(this);std::cout << "我是\"" << ++Customser::m_sNum << "\"号订购者。\n";m_number = Customser::m_sNum;}virtual void update(const std::string& message) override {m_message = message;printInfo();}void printInfo() {std::cout << "\"" << m_number << "\"号订购者:接收到新的消息:" << m_message << "\n";}void removeFromList() {m_mate50->detach(this);std::cout << "\"" << m_number << "\"号订购者:从列表中移除。\n";}
};int Customser::m_sNum = 0;int main() {Mate50* mate50 = new Mate50();Customser* c1 = new Customser(mate50);Customser* c2 = new Customser(mate50);Customser* c3 = new Customser(mate50);Customser* c4;Customser* c5;mate50->createMessage("Mate50即将到店......\n");c4 = new Customser(mate50);mate50->createMessage("Mate50即将到店......\n");c5 = new Customser(mate50);c2->removeFromList();mate50->createMessage("Mate50即将售罄......\n");delete mate50;delete c1;delete c2;delete c3;delete c4;delete c5;return 0;
}
定义对象间一种一对多的关系,当一个对象的状态发生变化的时候,所有依赖于它的对象都得到通知并自动更新在产品类中有用户列表,在用户类中有产品的基类,通过这样建立联系
状态
对象行为型
问题背景:开发一个糖果贩卖机,当投入硬币按下按钮,糖果机将掉落一枚糖果。当没有投入硬币,直接按下按钮,将会得到请投币的提示
#include <iostream>
#include <string>class State {
public:virtual ~State() {}virtual void getCandy() = 0;virtual void returnCoin() = 0;virtual void putCoin() = 0;
};class NoCoin : public State {
public:virtual void getCandy() override {std::cout << "请先投币。\n";}virtual void returnCoin() override {std::cout << "你并没有投币。\n";}virtual void putCoin() override {std::cout << "投币成功。\n";}
};class HaveCoin : public State {
public:virtual void getCandy() override {std::cout << "糖果投放中...\n";}virtual void returnCoin() override {std::cout << "硬币退回中...\n";}virtual void putCoin() override {std::cout << "重复投币\n";}
};class CandyMachine {
private:State* m_curState;State* m_haveCoin;State* m_noCoin;public:CandyMachine() {m_haveCoin = new HaveCoin();m_noCoin = new NoCoin();m_curState = m_noCoin;std::cout << "糖果机:当前状态为--->" << typeid(*m_curState).name() << "。\n"; //获取类的名称的写法}~CandyMachine() {delete m_haveCoin;delete m_noCoin;}void putCoin() {std::cout << "糖果机:putCoind。\n";m_curState->putCoin();transitionTo(m_haveCoin);}void getCandy() {std::cout << "糖果机:getCandy。\n";m_curState->getCandy();transitionTo(m_noCoin);}void returnCoin() {std::cout << "糖果机:returnCoin。\n";m_curState->returnCoin();transitionTo(m_noCoin);}private:void transitionTo(State* state) {m_curState = state;std::cout << "糖果机:切换状态为--->" << typeid(*m_curState).name() << "。\n";}
};int main() {CandyMachine* cm = new CandyMachine;cm->getCandy();cm->returnCoin();cm->putCoin();cm->getCandy();cm->returnCoin();delete cm;return 0;
}
*策略
对象行为型
问题背景:做一款打斗游戏,玩家使用的英雄使用不同的武器将会产生不同的损伤效果
#include <iostream>
#include <string>class Weapon {
public:virtual std::string fight() const = 0;
};class Nife : public Weapon {
public:virtual std::string fight() const override {return "使用匕首计算损伤。";}
};class Axe : public Weapon {
public:virtual std::string fight() const override {return "使用斧子计算损伤。";}
};class Hero {
private:Weapon* m_weapon;public:Hero(Weapon* weapon = nullptr) : m_weapon(weapon) {}void setWeapon(Weapon* weapon) {m_weapon = weapon;}void fight() {std::cout << m_weapon->fight() << "\n";}
};int main() {std::cout << "客户端:英雄使用匕首攻击。\n";Nife nife;Hero hero(&nife);hero.fight();std::cout << "客户端:英雄使用斧子攻击。\n";Axe axe;hero.setWeapon(&axe);hero.fight();return 0;
}
模板方法
类行为型
问题背景:做一款数据挖掘的程序,需要支持不同格式的数据文件,虽然文件格式不同,实现步骤基本一致
#include <iostream>
#include <string>class DataMiner {
public://template methodvoid mineData(std::string path) {openFile(path);extractData();makeReport();hook1();closeFile();}protected:virtual void openFile(std::string path) = 0;void extractData() const {std::cout << "DataMiner:从字符串中提取相关数据。\n";}void makeReport() const {std::cout << "DataMiner:生成数据分析报告。\n";}virtual void closeFile() const = 0;virtual void hook1() const {}protected:std::string m_str = "";
};class PDFDataMiner : public DataMiner {
public:virtual void openFile(std::string path) override {m_str = "openfile(file)";std::cout << "PDFDataMiner:打开PDF文件,转换为字符串序列。\n";}virtual void closeFile() const override {std::cout << "PDFDataMiner:关闭PDF文件。\n";}
};class WordDataMiner : public DataMiner {
public:virtual void openFile(std::string path) override {m_str = "openfile(file)";std::cout << "WordDataMiner:打开Word文件,转换为字符串序列。\n";}virtual void closeFile() const override {std::cout << "WordDataMiner:关闭PDF文件。\n";}virtual void hook1() const {std::cout << "WordDataMiner:给word文件添加水印。\n";}};//多态 父类指针指向子类对象
void clientCode(DataMiner* dm, std::string path) {dm->mineData(path);
}int main() {PDFDataMiner pdf;clientCode(&pdf, "aaa.pdf");WordDataMiner word;clientCode(&word, "aaa.word");return 0;
}
访问者
对象行为型
问题背景:做一款生成冰淇淋和雪糕的程序,现在希望为其添加糖霜,巧克力粉
MVC
Model(模型)、View(视图)、Control(控制器)