模式设计原则
依赖倒置原则
⾼层模块不应该依赖低层模块,⼆者都应该依赖抽象 ;
抽象不应该依赖具体实现,具体实现应该依赖于抽象;
⾃动驾驶系统公司是⾼层,汽⻋⽣产⼚商为低层,它们不应该互相依赖,⼀⽅变动另⼀⽅也会
跟着变动;⽽应该 抽象 ⼀个⾃动驾驶⾏业标准,⾼层和低层都依赖它;这样以来就解耦了两⽅
的变动;⾃动驾驶系统、汽⻋⽣产⼚商都是具体实现,它们应该都依赖⾃动驾驶⾏业标准(抽
象);
开放封闭原则
⼀个类应该对扩展开放,对修改关闭;
⾯向接⼝编程
不将变量类型声明为某个特定的具体类,⽽是声明为某个接⼝。 客户程序⽆需获知对象的具体类型,只需要知道对象所具有的接⼝。
减少系统中各部分的依赖关系,从⽽实现 “ ⾼内聚、松耦合 ” 的类型设计⽅案。
封装变化点
将稳定点和变化点分离,扩展修改变化点; 让稳定点与变化点的实现层次分离 ;
单⼀职责原则
⼀个类应该仅有⼀个引起它变化的原因;
⾥⽒替换原则
⼦类型必须能够替换掉它的⽗类型;主要出现在⼦类覆盖⽗类实现,原来使⽤⽗类型的程序可能出现错误;覆盖了⽗类⽅法却没实现⽗类⽅法的 职责 ;
接⼝隔离原则
不应该强迫客户依赖于他们不⽤的⽅法;⼀般⽤于处理⼀个类拥有⽐较多的接⼝,⽽这些接⼝涉及到很多职责;对象组合优于类继承
继承耦合度⾼, 组合耦合度低;
创建型设计模式
简单工厂模式
#include <iostream>
using namespace std;
// 抽象汽车
class AbstractCar{
public:virtual void ShowCarName() = 0;
};
// 具体产品的汽车继承-->抽象汽车类,并且对它方法进行重写操作
// 凯美瑞
class Camry :public AbstractCar{virtual void ShowCarName() {cout << "Camry Car." << endl;}
};
// 迈腾
class Magotan :public AbstractCar{virtual void ShowCarName(){cout << "Magotan Car." << endl;}
};
// 奥迪
class Audi :public AbstractCar {virtual void ShowCarName() {cout << "Audi Car." << endl;}
};
// 奔驰
class Benz :public AbstractCar{virtual void ShowCarName() {cout << "Benz Car." << endl;}
};
// 通过传递参数来确定需要生成那汽车
// 汽车工厂
class CarFactory {
public:static AbstractCar* CreateCarFunc(string cname){if (cname == "Camry")// 具体生产细节......return new Camry;else if (cname == "Magotan")// 具体生产细节......return new Magotan;else if (cname == "Audi")// 具体生产细节......return new Audi;else if (cname == "Benz")// 具体生产细节......return new Benz;elsereturn nullptr; }
};
int main() {// 创建工厂CarFactory* fty = new CarFactory;// 创建汽车AbstractCar* car;// 指定工厂需要创建的汽车car = fty->CreateCarFunc("Benz");car->ShowCarName();car = fty->CreateCarFunc("Camry");car->ShowCarName();car = fty->CreateCarFunc("Audi");car->ShowCarName();car = fty->CreateCarFunc("Magotan");car->ShowCarName();return 0;
}
抽象工厂模式
抽象工厂模式(Abstract Factory Pattern)隶属于设计模式中的创建型模式,用于产品族的构建。抽象工厂是所有形态的工厂模式中最为抽象和最具一般性的一种形态。抽象工厂是指当有多个抽象角色时使用的一种工厂模式。抽象工厂模式可以向客户端提供一个接口,使客户端在不必指定产品的具体情况下,创建多个产品族中的产品对象。工厂模式中的每一个形态都是针对一定问题的解决方案,工厂方法针对的是多个产品系列结构;而抽象工厂模式针对的是多个产品族结构,一个产品族内有多个产品系列。
提供一个创建一系列相互依赖对象的接口,而无需指定它们具体的类。主要目的解决:主要解决接口问题的选择。
在抽象工厂模式当中,客户端不再负责对象的创建,而是把这个责任丢给具体的工厂类,客户端只负责对对象的调用,从而明确各个类的职责。抽象工厂模式当中存在四种角色:抽象工厂角色、具体工厂角色,抽象产品角色,具体产品角色。
#include <iostream>
using namespace std;
// 抽象水果
class AbstractFruit {
public:virtual void PrintName() = 0;AbstractFruit() {cout << "抽象水果构造函数." << endl;}~AbstractFruit() {cout << "抽象水果析构函数." << endl;}
};
// 抽象西瓜
class AbstractWatermelon : public AbstractFruit{
public:AbstractWatermelon() {cout << "抽象西瓜构造函数." << endl;}~AbstractWatermelon() {cout << "抽象西瓜析构函数." << endl;}
};
// 抽象桔子
class AbstractOrange : public AbstractFruit {
public:AbstractOrange() {cout << "抽象桔子构造函数." << endl;}~AbstractOrange() {cout << "抽象桔子析构函数." << endl;}
};
// 中国西瓜
class ChinaWatermelon :public AbstractWatermelon {
public:virtual void PrintName() {cout << "中国西瓜最好吃." << endl;}ChinaWatermelon() {cout << "中国西瓜构造函数." << endl;}~ChinaWatermelon() {cout << "中国西瓜析构函数." << endl;}
};
// 中国桔子
class ChinaOrange :public AbstractOrange
{
public:virtual void PrintName() {cout << "中国桔子最甜的.\n" << endl;}ChinaOrange() {cout << "中国桔子构造函数." << endl;}~ChinaOrange() {cout << "中国桔子析构函数" << endl;}
};
// 埃及西瓜
class EgyptWatermelon :public AbstractWatermelon {
public:virtual void PrintName() {cout << "埃及西瓜:早在四千年前就种植西瓜." << endl;}EgyptWatermelon() {cout << "埃及西瓜构造函数." << endl;}~EgyptWatermelon() {cout << "埃及西瓜析构函数." << endl;}
};
// 埃及桔子
class EgyptOrange :public AbstractOrange {
public:virtual void PrintName() {cout << "埃及桔子光照条件最好,供应高质量的桔子." << endl;}EgyptOrange() {cout << "埃及桔子构造函数." << endl;}~EgyptOrange() {cout << "埃及桔子析构函数." << endl;}
};
// 抽象工厂 主要针对产品转换
class AbstrctFactory {
public:virtual AbstractWatermelon* CreateWatermelon() = 0;virtual AbstractOrange* CreateOrange() = 0;AbstrctFactory() {cout << "抽象工厂构造函数." << endl;}~AbstrctFactory() {cout << "抽象工厂析构函数." << endl;}
};
// 中国工厂
class ChinaFactory :public AbstrctFactory
{
public:virtual AbstractWatermelon* CreateWatermelon() {return new ChinaWatermelon;}virtual AbstractOrange* CreateOrange() {return new ChinaOrange;}ChinaFactory() {cout << "中国工厂构造函数." << endl;}~ChinaFactory() {cout << "中国工厂析构函数." << endl;}
};
// 埃及工厂
class EgyptFactory :public AbstrctFactory {
public:virtual AbstractWatermelon* CreateWatermelon() {return new EgyptWatermelon;}virtual AbstractOrange* CreateOrange() {return new EgyptOrange;}EgyptFactory() {cout << "埃及工厂构造函数." << endl;}~EgyptFactory() {cout << "埃及工厂析构函数." << endl;}
};
int main() {cout << "****************************************************************************" << endl;AbstrctFactory* cfactory = new ChinaFactory;AbstractWatermelon* cwatermelon = cfactory->CreateWatermelon();AbstractOrange* corange = cfactory->CreateOrange();cwatermelon->PrintName();corange->PrintName();delete corange; corange = nullptr;delete cwatermelon; cwatermelon = nullptr;delete cfactory; cfactory = nullptr;cout << "****************************************************************************" << endl;cout << "\n\n****************************************************************************" << endl;AbstrctFactory* efactory = new EgyptFactory;AbstractWatermelon* ewatermelon = efactory->CreateWatermelon();AbstractOrange* eorange = efactory->CreateOrange();ewatermelon->PrintName();eorange->PrintName();delete eorange; eorange = nullptr;delete ewatermelon; ewatermelon = nullptr;delete efactory; efactory = nullptr;cout << "****************************************************************************" << endl;return 0;
}
原型模式
原型模式是一种创建型设计模式,其功能为复制一个运行时的对象,包括对象各个成员当前的值。而代码又能保持独立性。用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
主要解决:在运行期建立和删除原型
优点:性能提高、避免构造函数的约束
#include <iostream>
using namespace std;
class ProtoType {
public:ProtoType(){}~ProtoType() {}virtual ProtoType* CloneFunc() = 0;
};
class ConreteProtoType:public ProtoType {
public:ConreteProtoType(int imember):_member(imember) {cout << "执行ConreteProtoType带参构造函数.\n" << endl;}~ConreteProtoType() {cout << "执行ConreteProtoType析构函数." << endl;}// 拷贝构造函数(若有指针成员变量,要进行实现深拷贝)ConreteProtoType(const ConreteProtoType& rhs) {_member = rhs._member;cout << "数据成员_member1:" << _member << endl;}ConreteProtoType* CloneFunc() { // 派生类实现cout << "正在处理克隆." << endl;cout << "数据成员_member2:" << _member << endl;return new ConreteProtoType(*this);}
private:int _member;
};
int main() {cout << "main()函数-->原型模式开始.\n" << endl;ConreteProtoType* CloneObjA = new ConreteProtoType(88);ConreteProtoType* CloneObjB = CloneObjA->CloneFunc();return 0;
}
单例模式
单例模式的定义:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
单例模式是一种常用的软件设计模式。 在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源。如果希望在系统中某个类的对象只能存在一个,单例模式是最好的解决方案。
单例模式有 3 个特点
单例类只有一个实例对象
单例类必须自己创建自己的唯一实例
单例类对外提供一个访问该单例的全局访问点
主要解决:全局使用的类频繁地创建与销毁
优点:避免对资源的多重占用。在内存里只有一个实例,减少内存的开销,尤其是频繁的创建和销毁实例
#include <memory>
#define SINGLE_PTR(x) JF::SingletonPtr<x>::GetInstancePtr()
namespace JF {template<typename T , typename X = void , int N = 0>class Singleton{public:static T* GetInstance(){static T v;return &v;}};template<typename T , typename X = void , int N = 0>class SingletonPtr{public:static std::shared_ptr<T> GetInstancePtr(){static std::shared_ptr<T> v = std::make_shared<T>();return v;}};
}
建造者模式
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
实用范围:
1 当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时
2 当构造过程必须允许被构造的对象有不同表示时
Builder 模式叫建造者模式(或生成器模式),用来隐藏复合对象的创建过程。将复合对象创建过程加以抽象,通过派生类和重载的方式,动态地创建具有复合属性的对象。
#include <iostream>
#include <string.h>
using namespace std;
class Phone // 电话类
{
public:Phone() {cout << "调用Phone类的构造函数." << endl;}~Phone() {cout << "调用Phone类的析构函数." << endl;}void setCamera(string camera) {strCamera = camera;}void setBattery(string battery) {strBattery = battery;}void setScreen(string screen) {strScreen = screen;}void PrintCamera() {cout << "Camera-->" << strCamera.c_str() << endl;}void PrintBattery() {cout << "Battery-->" << strBattery.c_str() << endl;}void PrintScreen() {cout << "Screen-->" << strScreen.c_str() << endl;}
private:string strCamera; // 摄像头string strBattery; // 电池string strScreen; // 屏幕
};
class Fbuilder // 基类
{
public:Fbuilder() = default;~Fbuilder() = default;
protected:Phone* phone{nullptr}; // 电话对象
public:virtual void buildCamera() = 0;virtual void buildBattery() = 0;virtual void buildScreen() = 0;virtual Phone* GetPhone() {return phone;}
};
class IphoneBuilder :public Fbuilder { // 苹果派生类
public:IphoneBuilder() {phone = new Phone;}void buildCamera() {phone->setCamera("Iphone Camera Created.");}void buildBattery() {phone->setBattery("Iphone Battery Created.");}void buildScreen() {phone->setScreen("Iphone Screen Created.");}
};
class HuaweiBuilder :public Fbuilder { // 华为派生类
public:HuaweiBuilder() {phone = new Phone;}void buildCamera() {phone->setCamera("Huawei Camera Created.");}void buildBattery() {phone->setBattery("Huawei Battery Created.");}void buildScreen() { phone->setScreen("Huawei Screen Created."); }
};
class Director {
public:Director() = default;Director(Fbuilder* builder) { dbuilder = builder; }~Director() = default;void CreateFunc(Fbuilder* builder) {builder->buildCamera();builder->buildBattery();builder->buildScreen();}void CreateFunc() {dbuilder->buildCamera();dbuilder->buildBattery();dbuilder->buildScreen();}
private:Fbuilder *dbuilder{nullptr};
};int main() {Fbuilder* huawei = new HuaweiBuilder;Fbuilder* iphone = new IphoneBuilder;Director* director = new Director;director->CreateFunc(huawei);director->CreateFunc(iphone);Phone* huaweiphone = huawei->GetPhone();Phone* iphonephone = iphone->GetPhone();huaweiphone->PrintCamera();huaweiphone->PrintScreen();huaweiphone->PrintBattery();cout << endl;iphonephone->PrintCamera();iphonephone->PrintScreen();iphonephone->PrintBattery();return 0;
}
结构行设计模式
适配器模式
适配器模式定义:将一个类的接口转换成客户希望的另一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作
特点:
1、适配器模式:作为两个不兼容的接口之间的桥梁。它属于结构体型模式,结合两个独立接口的功能
2、主要解决:解决在软件系统当中,将一些“现存的对象”放到新的环境当中,而新环境要求的接口是现对象不能满足的
3、优点:可以让任何两个没有关联的类一起执行;为了提高类的利用;增加类的透明度;灵活性更好
4、缺点:适配器使用过多,让整个系统非常零乱,不容易整体进行把控。
#include <iostream>
using namespace std;
// 我们要定义客户端使用的接口,与特殊领域相关的
class Target {
public:virtual void RequestFunc() = 0;virtual ~Target() {cout << "调用Target类析构函数." << endl;}
};
// 已经存在的接口,这个接口需要被适配
class Adaptee {
public:void SpecificRequestFunc() {cout << "\nAadaptee类特殊请求处理实现模块.\n" << endl;}~Adaptee() {cout << "调用Adaptee类析构函数." << endl;}
};
// 适配器,将现在接口转为需要的接口
class Apapter :public Target {
private:Adaptee* adaptee;
public:Apapter() {adaptee = new Adaptee();cout << "调用Apapter类构造函数." << endl;}
public:virtual void RequestFunc() { // 可以转调已经实现的方法,进行适配adaptee->SpecificRequestFunc();}virtual ~Apapter() {delete adaptee;cout << "调用Apapter类析构函数." << endl;}
};
int main() {// 创建客户端需要调用的接口对象Target* target = new Apapter();target->RequestFunc(); // 请求处理操作if (target != NULL) {delete target;target = NULL;}return 0;
}
桥接模式
将抽象部分与它的实现部分分离,使它们都可以独立地变化
应用场景:
1 当一个类内部具备两种或多种变化维度时,使用桥接模式解耦这些变化的维度,使高层代码架构稳定
2 当一个类存在两个独立变化的维度,且这两个维度都需要进行扩展时
3 当一个系统需要在构件的抽象化角色和具体化角色之间增加更多的灵活性时
4 当一个系统不希望使用继承或因为多层次继承导致系统类的个数急剧增加时
#include <iostream>
using namespace std;
// 支付模式--实现化角色(实现类接口,Implementation(实现类接口))
class IPayMode {
public:virtual bool security(string Uid) = 0;
};
// 具体实现化角色:密码支付(具体实现类)
class PayCypher :public IPayMode {
public:bool security(string uId) override {cout << "密码支付,风控校验环境安全." << endl;return true;}
};
// 人脸支付
class PayFaceMode :public IPayMode {
public:bool security(string uId) override {cout << "人脸支付,风控校验脸部识别." << endl;return true;}
};
// 指纹支付
class PayFingerPrintMode :public IPayMode {
public:bool security(string uId) override {cout << "指纹支付,风控校验指令信息安全." << endl;return true;}
};
// 抽象化类:支付(抽象化角色)
class Pay {
public:IPayMode *payMode;Pay(IPayMode* payMode) {this->payMode = payMode; // 抽象类定义一个IPayMode,跟IPayMode存在关联关系}virtual ~Pay() {delete payMode;}virtual string transfer(string uId, string tradeId, long long amount) = 0;
};
// 扩展抽象化角色:微信支付
class WxPay :public Pay {
public:WxPay(IPayMode* payMode) :Pay(payMode) {}// 扩展抽象类(实现抽象类中定义的成员函数)string transfer(string uId, string tradeId, long long amount) {cout << "微信支付开始,用户ID:" << uId << "交易ID:" << tradeId << "交易金额:" << amount << endl;bool security = payMode->security(uId);if (!security){cout << "微信支付失败,用户ID:" << uId << "交易ID:" << tradeId << "交易金额:" << amount << endl;return "Fail000";}else {cout << "微信支付成功,用户ID:" << uId << "交易ID:" << tradeId << "交易金额:" << amount << endl;return "Success001";}}
};
// 扩展抽象化角色:支付宝支付
class AliPay :public Pay {
public:AliPay(IPayMode* payMode) :Pay(payMode) {}// 扩展抽象类(实现抽象类中定义的成员函数)string transfer(string uId, string tradeId, long long amount) {cout << "支付宝支付开始,用户ID:" << uId << "交易ID:" << tradeId << "交易金额:" << amount << endl;bool security = payMode->security(uId);if (!security){cout << "支付宝支付失败,用户ID:" << uId << "交易ID:" << tradeId << "交易金额:" << amount << endl;return "Fail000";}else {cout << "支付宝支付成功,用户ID:" << uId << "交易ID:" << tradeId << "交易金额:" << amount << endl;return "Success001";}}
};
// 扩展抽象化角色:华为支付
class HuaweiPay :public Pay {
public:HuaweiPay(IPayMode* payMode) :Pay(payMode) {}// 扩展抽象类(实现抽象类中定义的成员函数)string transfer(string uId, string tradeId, long long amount) {cout << "华为支付开始,用户ID:" << uId << "交易ID:" << tradeId << "交易金额:" << amount << endl;bool security = payMode->security(uId);if (!security) {cout << "华为支付失败,用户ID:" << uId << "交易ID:" << tradeId << "交易金额:" << amount << endl;return "Fail000";}else {cout << "华为支付成功,用户ID:" << uId << "交易ID:" << tradeId << "交易金额:" << amount << endl;return "Success001";}}
};
int main() {cout << "--------------------请选择付款方式--------------------" << endl;Pay* wxpay = new WxPay(new PayFaceMode());wxpay->transfer("weixin_666", "20221201", 290000);cout << endl << endl;cout << "--------------------请选择付款方式--------------------" << endl;Pay* huawei = new HuaweiPay(new PayCypher());huawei->transfer("Huawei_888", "20221208", 1000000);cout << endl << endl;cout << "--------------------请选择付款方式--------------------" << endl;Pay* alipay = new AliPay(new PayFingerPrintMode());alipay->transfer("Alipay_999", "20221209", 9000000);cout << endl << endl;return 0;
}
组合实体模式
将对象组合成树型结构以表示“部分-整体”的层次结构。组合实体模式使得用户对象单个对象和组合对象的使用具有一致性
组合模式的目的
让客户端不再区分操作的是组合对象还是叶子对象,而是以一个统一的方式来操作
组合模式的优点及缺点
优点:定义包含基本对象和组合对象的类层次结构;统一组合对象和叶子对象;简化客户端调用;更容易扩展
缺点:很难限制组合中的组件类型
#include <iostream>
#include <string>
#include <list>
using namespace std;
// 抽象的组件对象
class Component {
public:Component(string name) {strname = name; }virtual void add(Component* com) = 0;virtual void del(Component* com) = 0;virtual void print(int depths) = 0;
protected:string strname;
};
// Leaf在组合中表示叶子节点对象(叶子节点没有子节点)
class Leaf :public Component {
public:Leaf(string name) :Component(name) {}void add(Component* com) {cout << "无法添加叶子节点" << endl;}void del(Component* com) {cout << "无法删除叶子节点" << endl;}void print(int depths) {cout << string(depths, '-') + strname << endl;}
};
// 组合对象
class Composite :public Component {
public:Composite(string name) :Component(name) { }void add(Component* com) {children.push_back(com);}void del(Component* com) {children.remove(com);}// 输出枝节点名称,并对其下级进行遍历 void print(int depths) {cout << string(depths, '-') + strname << endl;for (Component* com : children) {com->print(depths + 2);}}
protected:// 定义子对象你方便,用来存储下属叶子节点和枝节点list<Component*> children;
};int main() {// 生成树根root ,根上长出两叶子LeafA LeafBComposite* root = new Composite("root树根");root->add(new Leaf("LeafA"));root->add(new Leaf("LeafB"));Composite* compx = new Composite("CompositeX");compx->add(new Leaf("CompositeX-LeafX-A"));compx->add(new Leaf("CompositeX-LeafX-B"));root->add(compx);Composite* compy = new Composite("CompositeY");compy->add(new Leaf("CompositeY-LeafY-A"));compy->add(new Leaf("CompositeY-LeafY-B"));root->add(compy);root->add(new Leaf("LeafC"));// 显示树的结构root->print(1);return 0;
}
装饰器模式
装饰器模式(Decorator Pattern)也称为包装模式(Wrapper Pattern),动态地给一个对象添加一些额外的职责。就增加功能来说,装饰器模式相比生成子类更为灵活
优点:
比继承更加灵活;简化高层定义
缺点:
会产生很多粒度对象
#include <iostream>
#include <string>
using namespace std;
class Car {
public:virtual void show() = 0;
};
// 汽车:装饰器的基类
class CarDecorator :public Car {CarDecorator(Car* p) :pCar() { }
private:Car* pCar;
};
// 4个实体的汽车类
class Volkswagen :public Car {
public:void show() { cout << "大众汽车配置:基本配置"; }
};
class Byd :public Car {
public:void show() { cout << "比亚迪汽车配置:基本配置"; }
};
class Benz :public Car {
public:void show() { cout << "奔驰汽车配置:基本配置";}
};
class Toyota :public Car {
public:void show() { cout << "丰田汽车配置:基本配置"; }
};
// 装饰器1:自动泊车入位
class ConcreteDecorator1 :public Car {
public:ConcreteDecorator1(Car* p) :pCar(p) { }void show() {pCar->show();cout << ",自动泊车入位";}
private:Car* pCar;
};
// 装饰器2:自动刹车
class ConcreteDecorator2 :public Car {
public:ConcreteDecorator2(Car* p) :pCar(p) { }void show() {pCar->show();cout << ",自动刹车";}
private:Car* pCar;
};
// 装饰器3:车联网
class ConcreteDecorator3 :public Car {
public:ConcreteDecorator3(Car* p) :pCar(p) { }void show() {pCar->show();cout << ",车联网";}
private:Car* pCar;
};
// 装饰器4:道路交通标识识别
class ConcreteDecorator4 :public Car {
public:ConcreteDecorator4(Car* p) :pCar(p) { }void show() {pCar->show();cout << ",道路交通标识识别";}
private:Car* pCar;
};
int main() {Car* pobj1 = new ConcreteDecorator1(new Volkswagen());pobj1 = new ConcreteDecorator2(pobj1);pobj1->show();cout << endl;Car* pobj2 = new ConcreteDecorator1(new Benz());pobj2 = new ConcreteDecorator2(pobj2);pobj2 = new ConcreteDecorator3(pobj2);pobj2 = new ConcreteDecorator4(pobj2);pobj2->show();cout << endl;return 0;
}
外观模式
为子系统的一组接口提供一个统一的接口,该模式定义了一个高层接口,这一个高层接口使的子系统更加容易使用。并且外观模式可以解决层结构分离、降低系统耦合度和为新旧系统交互提供接口功能
Facede:这个外观类为子系统提供一个共同的对外接口
Client:客户对象通过一个外观接口读写子系统中各接口的数据资料
适应场景
设计初期阶段,应该有意识的将不同层分离,层与层之间建立外观模式;在开发阶段,子系统越来越复杂,增加外观械提供一个简单的调用接口
优点
实现子系统与客户端之间松耦合关系;客户端屏蔽子系统组件,减少客户端所需处理的对象数目,并且使得子系统使用起来更加容易
#include <iostream>
#include <string>
using namespace std;
class systemtest1
{
public:void MethodFunc1(){cout << "MethodFunc1" << endl; }
};
class systemtest2
{
public:void MethodFunc2() {cout << "MethodFunc2" << endl;}
};
class systemtest3
{
public:void MethodFunc3() {cout << "MethodFunc3" << endl;}
};
class systemtest4
{
public:void MethodFunc4() {cout << "MethodFunc4" << endl;}
};
class systemtest5
{
public:void MethodFunc5(){cout << "MethodFunc5" << endl; }
};
class systemtest6
{
public:void MethodFunc6(){ cout << "MethodFunc6" << endl; }
};
// 外观类,需要掌握所有的子系统的方法和属性,进程能使目的为方便外界调用
class Facade {
public:Facade() {s1 = new systemtest1();s2 = new systemtest2();s3 = new systemtest3();s4 = new systemtest4();s5 = new systemtest5();s6 = new systemtest6();}void MethodFunc1() {s1->MethodFunc1();s2->MethodFunc2();s3->MethodFunc3();}void MethodFunc2() {s4->MethodFunc4();s5->MethodFunc5();s6->MethodFunc6();}
private:systemtest1* s1;systemtest2* s2;systemtest3* s3;systemtest4* s4;systemtest5* s5;systemtest6* s6;
};
int main() {Facade* fobj = new Facade(); // 由于Facade功能:客户端可以根本不知道这几子系统类的存在fobj->MethodFunc1();fobj->MethodFunc2();return 0;
}
享元模式
运用共享技术有效地支持大量细粒度的对象
Flyweight:享元接口,通过此接口 Flyweight 可以接受并作用于外部状态
ConcreteFlyweight:具体的享元实现对象,必须是可共享的,需要封装 Flyweight 的内部状态
UnsharedConcreteFlyweight:非共享的享元实现对象,并不是所有的 Flyweight 实现对象都需要共享
FlyweightFactory:享元工厂,主要用来创建并且管理共享的享元对象,并对外提供访问共享享元的接口
Client:享元客户端,主要的工作是维护一个对 Flayweight 的引用,计算或存储享元对象的外部状态
#include <iostream>
#include <map>
using namespace std;
// 1:定义抽象享元类。比如网络设备:路由器、交换机、集线器等等
class NetDevice {
public:virtual string devicetype() = 0;virtual void link() = 0;
};
// 2:具体享元类
class Router :public NetDevice {
public:Router(string type) {this->type = type;}string devicetype() {return this->type;}void link() {cout << "连接型号为:" << this->type << " 路由器." << endl;}
private:string type;
};
class Switch :public NetDevice {
public:Switch(string type) {this->type = type;}string devicetype() {return this->type;}void link() {cout << "连接型号为:" << this->type << " 交换机." << endl;}
private:string type;
};
class Hub :public NetDevice {
public:Hub(string type) {this->type = type;}string devicetype() {return this->type;}void link() {cout << "连接型号为:" << this->type << " 集线器." << endl;}
private:string type;
};
// 3:享元工厂类
class DeviceFactory {
public:DeviceFactory() {shared_ptr<NetDevice> d1 = make_shared<Router>("TP-Link-01");devis.insert(make_pair("Tp", d1));shared_ptr<NetDevice> d2 = make_shared<Switch>("华为-01");devis.insert(make_pair("Huawei", d2));shared_ptr<NetDevice> d3 = make_shared<Hub>("中兴-01");devis.insert(make_pair("Zte", d3));}shared_ptr<NetDevice> getnetdevice(string type) {if (devis.count(type)){count++;return devis.find(type)->second;}else{return nullptr;}}int gettotaldevice() {return devis.size();}int getterminalcount() {return count;}
private:map<string, shared_ptr<NetDevice>> devis;int count = 0;
};
int main(){shared_ptr<NetDevice> d1, d2, d3, d4, d5, d6, d7, d8;shared_ptr<DeviceFactory> df = make_shared<DeviceFactory>();d1 = df->getnetdevice("Huawei");d1->link();d2 = df->getnetdevice("Huawei");d2->link();d3 = df->getnetdevice("Huawei");d3->link();d4 = df->getnetdevice("Tp");d4->link();d5 = df->getnetdevice("Tp");d5->link();d6 = df->getnetdevice("Tp");d6->link();d7 = df->getnetdevice("Zte");d7->link();d8 = df->getnetdevice("Zte");d8->link();cout << "网络设备总数:" << df->gettotaldevice() << endl;cout << "网络终端总数:" << df->getterminalcount() << endl << endl;return 0;
}
代理模式
为其他对象提供一种代理以控制对这个对象的访问。一个类代表另一个类的功能(属于结构型模式)。代理模式的结构图如下
Subject:目标接口,定义代理和具体目标对象的接口,这样就可以在任何使用具体目标对象的地方使用代理对象
RealSubject:具体的目标对象,真正实现目标接口要求的功能
Proxy:代理对象
应用场景 优化接口性能
优点和缺点 职责非常清晰;高扩展性;智能化。造成请求的处理速度慢;实现非常复杂
#include <iostream>
using namespace std;
// Subject:目标接口
class Person {
public:virtual void RentHouse() = 0;
};
//realSubject:具体的目标对象
class Amy :public Person {
public:void RentHouse() { cout << "Amy想要租房:一套豪华别墅。" << endl; }
};
//realSubject:具体的目标对象
class Sunny :public Person {
public:void RentHouse() { cout << "Sunny想要租房:一套豪华别墅。" << endl; }
};
// Proxy:代理对象
class Proxy :public Person {
public:Proxy(Person* person) :objPerson(person) { cout << "调用Proxy代理对象类的构造函数。" << endl; }void RentHouse() {objPerson->RentHouse();cout << "解决方案:找Proxy中介公司来代理找豪华别墅。" << endl;}
private:Person* objPerson;
};
int main(){Person* amy = new Amy;Person* proxyamy1 = new Proxy(amy);proxyamy1->RentHouse();Person* sunny = new Sunny;Person* proxyamy2 = new Proxy(sunny);proxyamy2->RentHouse();return 0;
}
行为模式
责任链模式
使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。责任链模式的结构图如下
Handler:定义职责的接口,通常在这里定义处理请求的方法,可以在这里实现后继链
ConcreteHandler:实现职责的类,在这个类中,实现对在它职责范围内请求的处理,如果不处理,就继续转发请求给后继者。
Client:职责链的客户端,向链上的具体处理对象提交请求,让职责链负责处理
应用场景
相似审批请假流程
责任链优点和缺点
降低耦合度
简化对象
增强给对象指派职责的灵活性
增加新的请求处理类非常方便
不能够保证你的请求一定被接收
#include <iostream>
using namespace std;
// 抽象处理者:领导者类
class Leader {
public:void SetNext(Leader* next) { this->mnext = next; }Leader* GetNext()const { return mnext; }virtual ~Leader() { }// 处理请求方法virtual void HandlerRequest(int days) = 0;
private:Leader* mnext;
};
// 具体处理者1:班主任
class headmaster :public Leader {
public:void HandlerRequest(int days) override {if (days <= 3){ cout << "\n班主任已经批准你请假:" << days << "天。" << endl; } else {if (GetNext() != nullptr){GetNext()->HandlerRequest(days);} else {cout << "\n你请假的天数太多,没有人能够批准你请假。" << endl;}}}
};
// 具体处理者2:系主任
class departmentHead :public Leader {
public:void HandlerRequest(int days)override {if (days <= 10) {cout << "\n系主任已经批准你请假:" << days << "天。" << endl;}else {if (GetNext() != nullptr) {GetNext()->HandlerRequest(days);} else {cout << "\n你请假的天数太多,没有人能够批准你请假。" << endl;}}}
};
// 具体处理者3:校长
class principal :public Leader {
public:void HandlerRequest(int days)override {if (days <= 30) {cout << "\n校长已经批准你请假:" << days << "天。" << endl;} else {if (GetNext() != nullptr) {GetNext()->HandlerRequest(days);} else {cout << "\n你请假的天数太多,没有人能够批准你请假。" << endl;}}}
};
int main() {// 组装责任链Leader* t1 = new headmaster();Leader* t2 = new departmentHead();Leader* t3 = new principal();t1->SetNext(t2);t2->SetNext(t3);// 提交请假请求天数dayint day = 0;cout << "\n\n请输入请假天数:";while (cin >> day) {if (day == -1)break;t1->HandlerRequest(day);}return 0;
}
中介者模式
用一个中介对象来封装一系列的对象交互。中介者使得各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互
中介者模式主要用来降低多个对象和类之间的通信复杂性问题。属于行为型模式
Mediator:中介者接口。在里面定义各个同事之间交互需要的方法,可以是公共的通信方法,比如:changed 方法,大家都用,也可以是小范围的交互方法。
ConcreteMediator:具体中介者实现对象。它需要了解并维护各个同事对象,并负责具体的协调各同事对象的交互关系
Colleague:同事类的定义,通常实现成为抽象类,主要负责约束同事对象的类型,并实现一些具体同事类之间的公共功能,比如,每个具体同事类都应该知道中介者对象,也就是具体同事类都会有中介者对象,都可以定义到这个类里面
ConcreteColleague:具体的同事类,实现自已的业务,在需要与其他同事通信的时候,就与持有的中介者通信,中介者会负责与其他的同事交互
中介者模式的优点和缺点
松散耦合;集中控制交互;多对多变成一对多。中介者模式潜在缺点为过度集中化
class Mediator;
// 1. 抽象同事类
class Colleague {
public:Colleague(Mediator* pMediator) : mpMediator(pMediator) {} // 获取中介者对象virtual void SendFunc(char* msg) = 0;
protected:Mediator* mpMediator;
};
// 2. 主管类 (中介者)
class Mediator {
public:virtual void SendFunc(char* msg , Colleague* pColleague) = 0;
};
// 3. 具体同事
class ConcreteColleagueA : public Colleague {
public:ConcreteColleagueA(Mediator* pMediator) : Colleague(pMediator) {}void SendFunc(char* msg) override { mpMediator->SendFunc(msg , this); }void Notify(char* msg) {cout << "同事A获取消息: " << msg << endl;}
};
class ConcreteColleagueB : public Colleague {
public:ConcreteColleagueB(Mediator* pMediator) : Colleague(pMediator) {}void SendFunc(char* msg) override { mpMediator->SendFunc(msg, this); }void Notify(char* msg) {cout << "同事B获取消息: " << msg << endl;}
};
// 4. 具体主管
class ConcreteMediator : public Mediator {
public:// 重写声明方法,实现3个对象通信问题 A B Cvoid SendFunc(char* msg, Colleague* pColleague) override {ConcreteColleagueA* pColleagueA = dynamic_cast<ConcreteColleagueA*>(pColleague);if (pColleagueA) {cout << ": 消息来自同事A" << endl;if (mpColleagueB){mpColleagueB->Notify(msg);}} else {cout << ": 消息来自同事B" << endl;if (mpColleagueA) {mpColleagueA->Notify(msg);} else {cout << "没有同事A" << endl;}}}// 具体主管了解如下所有同事,所以拥有A,B,C所有特性void setColleagueA(Colleague* p) { mpColleagueA = dynamic_cast<ConcreteColleagueA*>(p); }void setColleagueB(Colleague* p) { mpColleagueB = dynamic_cast<ConcreteColleagueB*>(p); }
private:ConcreteColleagueA* mpColleagueA{ nullptr };ConcreteColleagueB* mpColleagueB{ nullptr };
};
int main() {Mediator* pMediator = new ConcreteMediator();Colleague* pColleagueA = new ConcreteColleagueA(pMediator);Colleague* pColleagueB = new ConcreteColleagueB(pMediator);ConcreteMediator* Mediator = dynamic_cast<ConcreteMediator*>(pMediator);Mediator->setColleagueA(pColleagueA);Mediator->setColleagueB(pColleagueB);char msg[50] = "你本周任务完成了吗?";pColleagueA->SendFunc(msg);char msg1[50] = "目标任务还没完成!";pColleagueB->SendFunc(msg1);return 0;
}
策略模式
定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换。此模式使得算法可独立于使用它的客户而变化
策略模式的本质
分离算法选择实现
Strategy:策略接口,用来约束一系列具体的策略算法。Context使用这个接口来调用具体的策略实现定义的算法
Context:上下文,负责和具体的策略类交互
ConcreteStrategy:具体的策略实现,也就是具体的算法实现
策略模式:一个类的行为或其算法可以在运行时修改。此模式属于行为型模式。策略对象改变 context 对象的执行算法
优点与缺点
定义一系列算法;避免多重条件语句;更的扩展性。客户必须了解每种策略的不同;增加了对象数目;只适合扁平的算法结构
#include <iostream>
using namespace std;
#define freeptr(p) if(p) delete p; p=nullptr;
// 设计所有支持算法的公共接口 Strategy类
class Strategy
{
public:~Strategy(){ cout << "调用Strategy类-->析构函数." << endl; };virtual void AlgorithmInterfaceFunc() = 0;
};
// 继承Strategy类,封装具体算法和行为
class ConcreteStrategyA :public Strategy {void AlgorithmInterfaceFunc() { cout << "调用ConcreteStrategyA类-->算法A操作实现." << endl; }
};
class ConcreteStrategyB :public Strategy {void AlgorithmInterfaceFunc() { cout << "调用ConcreteStrategyB类-->算法B操作实现." << endl; }
};
class ConcreteStrategyC :public Strategy {void AlgorithmInterfaceFunc() { cout << "调用ConcreteStrategyC类-->算法C操作实现." << endl; }
};
class Context {
public:Context(Strategy* strategy) :mstrategy(strategy) { }~Context() { freeptr(mstrategy); }void AlgorithmInterfaceFunc() { mstrategy->AlgorithmInterfaceFunc(); }
private:Strategy* mstrategy;
};int main()
{Strategy* concretestrategyA = new ConcreteStrategyA();Strategy* concretestrategyB = new ConcreteStrategyB();Strategy* concretestrategyC = new ConcreteStrategyC();Context* ctx = new Context(concretestrategyA);ctx->AlgorithmInterfaceFunc();return 0;
}
模板模式
定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法模式使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤
AbstractClass:抽象类。用来定义算法骨架和原语操作,具体的子类通过重定义这些原语操作来实现一个算法的各个步骤。在这个类里面,还可以提供算法中通用的实现。
ConcreteClass:具体实现类。用来实现算法骨架中的某些步骤,完成与特定子类相关的功能
优点
实现代码复用。算法骨架不容易升级
#include <iostream>
using namespace std;
class AbstractClass {
public:void TemplateMethod() {cout << "调用:模板方法模式." << endl;PrimitiveOperation1();PrimitiveOperation2();}
protected:virtual void PrimitiveOperation1() { cout << "默认操作--Operation1." << endl; }virtual void PrimitiveOperation2() { cout << "默认操作--Operation2." << endl; }
};
class ConreteClass1 :public AbstractClass {
protected:virtual void PrimitiveOperation1() { cout << "具体操作实现1--Operation1." << endl; }virtual void PrimitiveOperation2() { cout << "具体操作实现1--Operation2." << endl; }
};
class ConreteClass2 :public AbstractClass {
protected:virtual void PrimitiveOperation1() { cout << "具体操作实现2--Operation1." << endl; }virtual void PrimitiveOperation2() { cout << "具体操作实现2--Operation2." << endl; }
};
class ConreteClass3 :public AbstractClass {
protected:virtual void PrimitiveOperation1() { cout << "具体操作实现3--Operation1." << endl; }virtual void PrimitiveOperation2() { cout << "具体操作实现3--Operation2." << endl; }
};
int main() {AbstractClass* pabst1 = new ConreteClass1;pabst1->TemplateMethod();AbstractClass* pabst2 = new ConreteClass2;pabst2->TemplateMethod();AbstractClass* pabst3 = new ConreteClass3;pabst3->TemplateMethod();return 0;
}
状态模式
允许一个对象在其内部状态改变它的行为。对象看起来似乎修改了它的类
State:状态接口,用来封装与上下文的一个特定状态所对应的行为。
ConcreteState:具体实现状态处理类,每个类实现一个跟上下文相关的状态的具体处理
Context:环境,也称为上下文,通常用来定义客户感兴趣的接口,同时维护一个来具体处理当前状态的实例对象。
优点和缺点
简化应用逻辑控制;
更好地分离状态和行为;
更好的扩展性;
显式化进行状态转换。一个状态对应一个状态处理类,会让程序引入太多的状态类变得混乱
#include <iostream>
using namespace std;
class Context;
class State { // 状态接口
public:State() { cout << "调用:State构造函数." << endl; }~State() { cout << "调用:State析构函数." << endl; }virtual void Handle(Context* pContext) { }
};
class Context { // 环境(又称为上下文)
public:Context() { cout << "调用:Context默认构造函数." << endl; }Context(State* pstate) :pState(pstate) { }~Context() { cout << "调用:Context析构函数." << endl; }void Request() {if (pState) {pState->Handle(this);}}void ChangedState(State* p) {if (pState != NULL) {delete pState;pState = NULL;}pState = p;}
private:State* pState;
};
class ConcreteStateA :public State { // 具体实现状态处理类
public:void Handle(Context* pcontext);
};
class ConcreteStateB :public State { // 具体实现状态处理类
public:void Handle(Context* pcontext);
};
class ConcreteStateC :public State { // 具体实现状态处理类
public:void Handle(Context* pcontext);
};
void ConcreteStateA::Handle(Context* pcontext){cout << "第1种状态 A" << endl;pcontext->ChangedState(new ConcreteStateB());
}
void ConcreteStateB::Handle(Context* pcontext){cout << "第2种状态 B" << endl;pcontext->ChangedState(new ConcreteStateC());
}
void ConcreteStateC::Handle(Context* pcontext){cout << "第3种状态 C" << endl;pcontext->ChangedState(new ConcreteStateA());
}
int main() {State* pstate = new ConcreteStateA();Context* pcontext = new Context(pstate);pcontext->Request();pcontext->Request();pcontext->Request();pcontext->Request();return 0;
}
观察者模式
定义对象的一种一对多的依赖关系。当一个对象的状态发生改变时,所有依赖于它的对象都得到通知被自动更新
Subject:目标对象
Observer:定义观察者的接口
ConcreteSubject:具体的目标实现对象
ConcreteObserver:观察者的具体实现对象
优点和缺点
实现观察者和目标之间的抽象耦合
动态联动
支持广播通信
可能会引起无谓的操作
#include <iostream>
#include <list>
using namespace std;
class Observer { // 定义观察者的接口(抽象观察者)
public:virtual void Update(int) = 0;
};
class Subject { // 目标对象(抽象通知者)
public:virtual void Attach(Observer*) = 0;virtual void Detach(Observer*) = 0;virtual void Notify() = 0;
};
// 观察者的具体实现对象
class ConreteObserver1 :public Observer {
public:ConreteObserver1(Subject* psubject) :mpsubject(psubject) {}// Upadte()方法(更新方法)void Update(int values) { cout << "ConreteObserver1获取更新,新状态为:" << values << endl; }private:Subject* mpsubject;
};
class ConreteObserver2 :public Observer {
public:ConreteObserver2(Subject* psubject) :mpsubject(psubject) {}// Upadte()方法(更新方法)void Update(int values) { cout << "ConreteObserver2获取更新,新状态为:" << values << endl;}
private:Subject* mpsubject;
};
// 具体的目标实现对象
class ConceteSubject :public Subject {
public:void Attach(Observer* pobserver) { mobserverlist.push_back(pobserver); }void Detach(Observer* pobserver) { mobserverlist.remove(pobserver); }void Notify() {for (auto& iter : mobserverlist) {iter->Update(mstate);}}void SetState(int state) { mstate = state; } // 设置状态
private:int mstate;std::list<Observer*>mobserverlist;
};
int main() {// 创建目标对象ConceteSubject* psubject = new ConceteSubject();// 创建观察者Observer* pobserver1 = new ConreteObserver1(psubject);Observer* pobserver2 = new ConreteObserver2(psubject);// 更改状态psubject->SetState(666);// 注册观察者接口psubject->Attach(pobserver1);psubject->Attach(pobserver2);psubject->Notify();// 注销观察者psubject->Detach(pobserver1);psubject->SetState(888);psubject->Notify();return 0;
}
备忘录模式
在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将对象恢复到原先保存的状态
Memento:备忘录
Originator:原发器
Caretaker:备忘录管理者
优点和缺点
更好的封装性
简化原发器
窄接口和宽接口
可能导致高开销
#include <iostream>
#include <string>
using namespace std;
class Memento { // 备忘录
public:Memento(string name, int age) {this->mname = name;this->mage = age;}string getname() { return mname; }int agetage() { return mage; }void setname(string name) { this->mname = name; }void setage(int age) { this->mage = age; }
private:string mname;int mage;
};
class Person { // 原发器
public:Person(string name, int age) {this->mname = name;this->mage = age;}string getname() { return mname; }int agetage() { return mage; }void setname(string name) { this->mname = name; }void setage(int age) { this->mage = age; }Memento* creatememento() { return new Memento(mname, mage); }void setmemento(Memento* memento) {this->mname = memento->getname();this->mage = memento->agetage();}void dispfunc() { cout << "姓名:" << mname << ",年龄:" << mage << endl;}
private:string mname;int mage;
};
class Caretaker { // 备忘录管理者
public:Caretaker(Memento* memto) { this->mmemento = memto; }Memento* getMemento() { return this->mmemento; }void setmemento(Memento* memto) { this->mmemento = memto; }
private:Memento* mmemento;
};
int main(){Person* p = new Person("张三", 22);p->dispfunc();Caretaker* caretaker = new Caretaker(p->creatememento());p->setname("王刚");p->dispfunc();p->setmemento(caretaker->getMemento());p->dispfunc();return 0;
}
命令模式
将一个请求封装为一个对象,从而使您可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作
Command:定义命令接口
ConcreteCommand:命令接口实现对象
Invoker:要求命令对象执行请求
Client:创建具体的命令对象
Receiver:接收者
优点和缺点
更松散的耦合
更动态的控制
很自然的复合命令
更好的扩展性
应用命令模式可能会导致某些系统有过多的具体命令类,麻烦复杂
本质:
封装请求
#include <iostream>
using namespace std;
class Receiver { // 接收者
public:void ActionFunc() { cout<<"\nReceiver-->ActionFunc()"<<endl; }
};
class Command { // 写信命令接口
public:virtual void Execute() = 0;
};
class ConcreteCommand :public Command { // 命令接口实现对象
public:ConcreteCommand(Receiver* preceiver) :mpreceiver(preceiver){}void Execute() { mpreceiver->ActionFunc(); }
private:Receiver* mpreceiver;
};class Invoker { // 要求命令对象执行请求
public:Invoker(Command *pcommand):mpcommand(pcommand){}void Invoke() { mpcommand->Execute(); }
private:Command* mpcommand;
};
int main()
{Receiver* preceiver = new Receiver();Command* pcommand = new ConcreteCommand(preceiver);Invoker* pinvoker = new Invoker(pcommand);pinvoker->Invoke();return 0;
}
访问者模式
表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作
Visitor:访问者接口
ConcreteVisitor:具体的访问者实现对象
Element:被访问元素接口
ConcreteElement:具体元素实现对象
ObjectStructure:对象结构。
本质
预留通路,回调实现
优点与缺点
扩展性好
复用性好
分离无关行为
对象结构变化困难
破坏封装
#include <iostream>
#include <vector>
using namespace std;
// 具体元素(具体访问者实现accept()方法
class ConcreteElementA;
class ConcreteElementB;
class Visitor { // 抽象访问者类
public:virtual void VisitConcreteElementA(ConcreteElementA *pelementA) = 0;virtual void VisitConcreteElementB(ConcreteElementB* pelementB) = 0;
};
class ConreteVisitor1 :public Visitor { // 具体访问者类(实现每个抽象访问者声明操作)
public:void VisitConcreteElementA(ConcreteElementA* pelementA) { cout << "执行ConreteVisitor1::VisitConcreteElementA(...)函数." << endl; }void VisitConcreteElementB(ConcreteElementB* pelementB) { cout << "执行ConreteVisitor1::VisitConcreteElementB(...)函数." << endl; }
};
class ConreteVisitor2 :public Visitor { // 具体访问者类(实现每个抽象访问者声明操作)
public:void VisitConcreteElementA(ConcreteElementA* pelementA) { cout << "执行ConreteVisitor2::VisitConcreteElementA(...)函数." << endl; }void VisitConcreteElementB(ConcreteElementB* pelementB) { cout << "执行ConreteVisitor2::VisitConcreteElementB(...)函数." << endl; }
};
class Element { // 抽象元素(一般是抽象类或接口,此方法以一个抽象访问者作为参数
public:virtual void Accept(Visitor* pvisitor) = 0;
};
class ConcreteElementA :public Element {
public:ConcreteElementA() { cout << "执行ConreteElementA()构造函数." << endl; }void Accept(Visitor* pvisitor) { pvisitor->VisitConcreteElementA(this); }
};
class ConcreteElementB :public Element {
public:ConcreteElementB() { cout << "执行ConreteElementB()构造函数." << endl; }void Accept(Visitor* pvisitor) { pvisitor->VisitConcreteElementB(this); }
};
class ObjectStructure { // 对象结构类(是一个元素的集合,它主要用于存放元素对象,并且提供遍历其内部元素的方法
public:void Attach(Element* pelement) { elements.push_back(pelement); }void Detach(Element* pelement) {vector<Element*>::iterator it = find(elements.begin(), elements.end(), pelement);if (it != elements.end()) {elements.erase(it);}}void Accept(Visitor* pvisitor) {// 为每个element设置visitorfor (vector<Element*>::const_iterator it = elements.begin(); it != elements.end(); it++) {(*it)->Accept(pvisitor);}}
private:vector<Element*> elements;
};
int main(){ObjectStructure* pobj = new ObjectStructure;ConcreteElementA* pelmtA = new ConcreteElementA;ConcreteElementB* pelmtB = new ConcreteElementB;pobj->Attach(pelmtA);pobj->Attach(pelmtB);cout << endl;ConreteVisitor1* pvist1 = new ConreteVisitor1;ConreteVisitor2* pvist2 = new ConreteVisitor2;pobj->Accept(pvist1);pobj->Accept(pvist2);return 0;
}
解释器模式
给定一个语言,定义它的文法表示,并定义一个解释器,这个解释器使用该标识来解释语言中的句子
AbstractExpression:定义解释器的接口
TerminalExpression:终结符解释器
NonTerminalExpression:非终结符解释器
Context:上下文
Client:客户端
优点与缺点
易于扩展新的语法
易于实现语法
不适合复杂的语法
解释器模式会引起类膨胀
本质
分离实现,解释执行
#include <iostream>
#include <string>
#include <stack>
#include <vector>
#include <algorithm>
#include <unordered_map>
using namespace std;
// 抽象表达式类
class Expression {
public:virtual ~Expression(){}virtual double interpreter(unordered_map<string, double>var) = 0;
};
// 变量解析器类
class VarExpression :public Expression {
public:VarExpression(string key) : mkey(key){}double interpreter(unordered_map<string, double>var) override { return var[mkey]; }
private:string mkey;
};
// 抽象运算符号解析器
class SymbolExpression :public Expression {
public:SymbolExpression(Expression* left, Expression* right):mleft(left),mright(right){}
protected:Expression* mleft;Expression* mright;
};
// 设计加法解释器
class AddExpression :public SymbolExpression {
public:AddExpression(Expression* left, Expression* right) :SymbolExpression(left, right) {}double interpreter(unordered_map<string, double> var)override { return mleft->interpreter(var) + mright->interpreter(var); }
};
// 设计减法解释器
class SubExpression :public SymbolExpression {
public:SubExpression(Expression* left, Expression* right) :SymbolExpression(left, right) {}double interpreter(unordered_map<string, double> var)override { return mleft->interpreter(var) - mright->interpreter(var); }
};
// 设计解析器封装类
class Calculator {
public:Calculator(vector<string> expstr) {stack<Expression*> stack;Expression* left;Expression* right;for (int i = 0; i < expstr.size(); i++) {if (expstr[i] == "+") { // 加法操作left = stack.top(), stack.pop();right = new VarExpression(expstr[++i]);stack.push(new AddExpression(left, right));} else if (expstr[i] == "-") { // 减法操作left = stack.top(), stack.pop();right = new VarExpression(expstr[++i]);stack.push(new SubExpression(left, right));} else // 变量{stack.push(new VarExpression(expstr[i]));}}this->mpression = stack.top();}double run(unordered_map<string, double>var) {return this->mpression->interpreter(var);}
private:Expression* mpression;
};
// 客户端
// 获取表达式
void getexpstr(vector<string>& expstr) {cout << "\n请输入算术表达式:" << endl;string str;int currentindex = 0;getline(cin, str);string temp;int len = 0;for (int i = 0; i < str.size(); i++) {switch (str[i]) {case '+':len = i - currentindex;temp = str.substr(currentindex, len);// 多余的空格处理temp.erase(remove(temp.begin(), temp.end(), ' '), temp.end());expstr.push_back(temp);expstr.push_back("+");currentindex = i + 1;break;case '-':len = i - currentindex;temp = str.substr(currentindex, len);// 多余的空格处理temp.erase(remove(temp.begin(), temp.end(), ' '), temp.end());expstr.push_back(temp);expstr.push_back("-");currentindex = i + 1;break;}}temp = str.substr(currentindex);temp.erase(remove(temp.begin(), temp.end(), ' '), temp.end());expstr.push_back(temp);
}
void getvalue(unordered_map<string, double>& var, vector<string>& expstr) {for (const auto& key : expstr) {if (key != "+" && key != "-") {if (var.find(key) == var.end()) {cout << "请输入" << key << " 的值:" << endl;cin >> var[key];}}}
}
string vector_to_string(vector<string>& expStr) {string str;for (const auto& expstr : expStr) {str.append(expstr);str.append(" ");}str.pop_back();return str;
}
int main() {vector<string> expstr;unordered_map<string, double> var;getexpstr(expstr);getvalue(var, expstr);Calculator* calc = new Calculator(expstr);cout << "\n表达式计算结果为:" << vector_to_string(expstr) << " = " << calc->run(var) << endl;return 0;
}
迭代器模式
提供一种方法顺序访问一个聚合对象中的各个元素,而又不需要暴露该对象的内部表示
Iterator:迭代器接口
ConcreteIterator:具体的迭代器实现对象
Aggregate:聚合对象
ConcreteAggregate:具体聚合对象
#include <iostream>
#include <vector>
#include <string>
using namespace std;
// 迭代抽象类
class Iterator {
public:Iterator() {}virtual ~Iterator(){}virtual string First() = 0;virtual string Next() = 0;virtual string CurrentItem() = 0;virtual bool IsDone() = 0;
};
// 聚集抽象类
class Aggregate {
public:virtual int Count() = 0;virtual void Push(const string& strvalue) = 0;virtual string Pop(const int nindex) = 0;virtual Iterator* CreateIterator() = 0;
};
// 具体迭代器类,继承Iterator实现
class ConcreteIterator :public Iterator {
public:ConcreteIterator(Aggregate* paggreate) :mncurrent(0), Iterator() {maggreate = paggreate;}string First() { return maggreate->Pop(0); }string Next() {string strRet;mncurrent++;if (mncurrent < maggreate->Count()) {strRet = maggreate->Pop(mncurrent);}return strRet;}string CurrentItem(){return maggreate->Pop(mncurrent); }bool IsDone() { return ((mncurrent >= maggreate->Count()) ? true : false); }
private:int mncurrent;Aggregate* maggreate;
};
// 具体聚集类 继承
class ConcreteAggregate :public Aggregate {
public:ConcreteAggregate() : mpiterator(NULL) { mvecitems.clear(); }~ConcreteAggregate() {if (mpiterator != NULL) {delete mpiterator;mpiterator = NULL;} }Iterator* CreateIterator() {if (mpiterator == NULL) {mpiterator = new ConcreteIterator(this);}return mpiterator; }int Count() { return mvecitems.size(); }void Push(const string& strValue) { mvecitems.push_back(strValue); }string Pop(const int nIndex) {string strRet;if (nIndex < Count()) {strRet = mvecitems[nIndex];}return strRet;}
private:vector<string> mvecitems;Iterator* mpiterator;
};
int main() {ConcreteAggregate* pstr = new ConcreteAggregate();if (pstr != NULL) {pstr->Push("How are you:");pstr->Push("How do you do:");pstr->Push("What is you name:");}Iterator* it = pstr->CreateIterator();if (it != NULL) {string stritem = it->First();while (!it->IsDone()) {cout << it->CurrentItem() << " is OK." << endl;it->Next();}}return 0;
}