后端技术_结构型设计模式
最近更新:2024-09-23
|
字数总计:4.3k
|
阅读估时:19分钟
|
阅读量:次
- 单例模式
- 工厂模式
- 举例
- 抽象工厂
- 背景
- 责任链
- 举例
- 装饰器
- 举例
- 组合模式
- 举例
单例模式
- 保证一个类仅有一个实例,并且提供一个该实例的全局访问点
- 解决了什么问题:
- 稳定点:类只有一个实例,提供全局的访问点(抽象)
- 变化点:有多个类都是单例,能不能复用代码(扩展:组合、继承)
- 代码结构
- 私有的构造和析构
- 禁掉拷贝构造、拷贝赋值、移动构造、移动赋值
- 静态类成员函数
- 静态私有成员变量
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
|
class Singleton { public: static Singleton * GetInstance() { if (_instance == nullptr) { _instance = new Singleton(); } return _instance; } private: Singleton(){}; ~Singleton(){}; Singleton(const Singleton &) = delete; Singleton& operator=(const Singleton&) = delete; Singleton(Singleton &&) = delete; Singleton& operator=(Singleton &&) = delete; static Singleton * _instance; }; Singleton* Singleton::_instance = nullptr;
##include <cstdlib> class Singleton { public: static Singleton * GetInstance() { if (_instance == nullptr) { _instance = new Singleton(); atexit(Destructor); } return _instance; } private: static void Destructor() { if (nullptr != _instance) { delete _instance; _instance = nullptr; } } Singleton(){}; ~Singleton(){}; Singleton(const Singleton &) = delete; Singleton& operator=(const Singleton&) = delete; Singleton(Singleton &&) = delete; Singleton& operator=(Singleton &&) = delete; static Singleton * _instance; }; Singleton* Singleton::_instance = nullptr;
##include <mutex> class Singleton { public: static Singleton * GetInstance() { if (_instance == nullptr) { std::lock_guard<std::mutex> lock(_mutex); if (_instance == nullptr) { _instance = new Singleton(); atexit(Destructor); } } return _instance; } private: static void Destructor() { if (nullptr != _instance) { delete _instance; _instance = nullptr; } } Singleton(){}; ~Singleton(){}; Singleton(const Singleton &) = delete; Singleton& operator=(const Singleton&) = delete; Singleton(Singleton &&) = delete; Singleton& operator=(Singleton &&) = delete; static Singleton * _instance; static std::mutex _mutex; }; Singleton* Singleton::_instance = nullptr; std::mutex Singleton::_mutex;
##include <mutex> ##include <atomic> class Singleton { public: static Singleton * GetInstance() { Singleton* tmp = _instance.load(std::memory_order_relaxed); std::atomic_thread_fence(std::memory_order_acquire); if (tmp == nullptr) { std::lock_guard<std::mutex> lock(_mutex); tmp = _instance.load(std::memory_order_relaxed); if (tmp == nullptr) { tmp = new Singleton; std::atomic_thread_fence(std::memory_order_release); _instance.store(tmp, std::memory_order_relaxed); atexit(Destructor); } } return tmp; } private: static void Destructor() { Singleton* tmp = _instance.load(std::memory_order_relaxed); if (nullptr != tmp) { delete tmp; } } Singleton(){}; ~Singleton(){}; Singleton(const Singleton &) = delete; Singleton& operator=(const Singleton&) = delete; Singleton(Singleton &&) = delete; Singleton& operator=(Singleton &&) = delete; static std::atomic<Singleton*> _instance; static std::mutex _mutex; }; std::atomic<Singleton*> Singleton::_instance; std::mutex Singleton::_mutex;
class Singleton { public: static Singleton& GetInstance() { static Singleton instance; return instance; } private: Singleton(){}; ~Singleton(){}; Singleton(const Singleton &) = delete; Singleton& operator=(const Singleton&) = delete; Singleton(Singleton &&) = delete; Singleton& operator=(Singleton &&) = delete; };
template<typename T> class Singleton { public: static T& GetInstance() { static T instance; return instance; } protected: virtual ~Singleton() {} Singleton() {} private: Singleton(const Singleton &) = delete; Singleton& operator=(const Singleton&) = delete; Singleton(Singleton &&) = delete; Singleton& operator=(Singleton &&) = delete; };
class DesignPattern : public Singleton<DesignPattern> { friend class Singleton<DesignPattern>; private: DesignPattern() {} ~DesignPattern() {} };
|
工厂模式
- 定义一个用于创造对象的接口,让子类决定实例化哪一个类。工厂模式使得一个类的实例化延迟到子类。
- 为什么要有工厂模式,为不直接使用new?
- 解决了什么问题
- 稳定点:
- 创建同类对象的接口——对象创建接口
- 同类对象都有一个相同的职责——功能接口
- 变化点:创建对象的扩展
- 代码结构
- 对象创建接口,其中创建具体对象,调用功能接口
- 功能接口
- 设计原则:
- 如何扩展代码
举例
- 实现一个导出数据的接口,让客户选择数据的导出方式。
- 不使用设计模式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| ##include <string>
class IExport { public: virtual bool Export(const std::string &data) = 0; virtual ~IExport(){} };
class ExportXml : public IExport { public: virtual bool Export(const std::string &data) { return true; } };
class ExportJson : public IExport { public: virtual bool Export(const std::string &data) { return true; } };
class ExportTxt : public IExport { public: virtual bool Export(const std::string &data) { return true; } }; int main() { std::string choose; if (choose == "txt") { IExport *e = new ExportTxt(); e->Export("hello world"); } else if (choose == "json") { IExport *e = new ExportJson(); e->Export("hello world"); } else if (choose == "xml") { IExport *e = new ExportXml(); e->Export("hello world"); } else if (choose == "csv") { IExport *e = new ExportXml(); e->Export("hello world"); } }
|
- 使用设计模式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
| ##include <string>
class IExport { public: virtual bool Export(const std::string &data) = 0; virtual ~IExport(){} };
class ExportXml : public IExport { public: virtual bool Export(const std::string &data) { return true; } };
class ExportJson : public IExport { public: virtual bool Export(const std::string &data) { return true; } };
class ExportTxt : public IExport { public: virtual bool Export(const std::string &data) { return true; } };
class ExportCSV : public IExport { public: virtual bool Export(const std::string &data) { return true; } };
class IExportFactory { public: IExportFactory() { _export = nullptr; } virtual ~IExportFactory() { if (_export) { delete _export; _export = nullptr; } } bool Export(const std::string &data) { if (_export == nullptr) { _export = NewExport(); } return _export->Export(data); } protected: virtual IExport * NewExport() = 0; private: IExport* _export; };
class ExportXmlFactory : public IExportFactory { protected: virtual IExport * NewExport() { IExport * temp = new ExportXml(); return temp; } }; class ExportJsonFactory : public IExportFactory { protected: virtual IExport * NewExport() { IExport * temp = new ExportJson; return temp; } }; class ExportTxtFactory : public IExportFactory { protected: IExport * NewExport() { IExport * temp = new ExportTxt; return temp; } };
class ExportCSVFactory : public IExportFactory { protected: virtual IExport * NewExport() { IExport * temp = new ExportCSV; return temp; } };
int main () { IExportFactory *factory = new ExportCSVFactory(); factory->Export("hello world"); return 0; }
|
抽象工厂
- 提供一个接口,让该接口负责创建一系列“相关或者相互依赖的对象”,无需指定他们具有的类(实际上就是工厂模式的扩展,一个类有多个功能接口)
- 解决了什么问题
- 稳定点
- 创建同类对象的接口——对象创建接口
- 同类对象有多相同的职责——功能接口
- 变化点
- 代码结构
- 对象创建接口,其中创建具体对象,提供多个功能接口来调用
- 多个功能接口
- 工程模式与抽象工厂的区别:功能是否是一个
背景
- 实现一个拥有导入导出数据的接口,让客户选择数据导入导出的方式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177
| ##include <string>
class IExport { public: virtual bool Export(const std::string &data) = 0; virtual ~IExport(){} };
class ExportXml : public IExport { public: virtual bool Export(const std::string &data) { return true; } };
class ExportJson : public IExport { public: virtual bool Export(const std::string &data) { return true; } };
class ExportTxt : public IExport { public: virtual bool Export(const std::string &data) { return true; } };
class ExportCSV : public IExport { public: virtual bool Export(const std::string &data) { return true; } };
class IImport { public: virtual bool Import(const std::string &data) = 0; virtual ~IImport(){} };
class ImportXml : public IImport { public: virtual bool Import(const std::string &data) { return true; } };
class ImportJson : public IImport { public: virtual bool Import(const std::string &data) { return true; } };
class ImportTxt : public IImport { public: virtual bool Import(const std::string &data) { return true; } };
class ImportCSV : public IImport { public: virtual bool Import(const std::string &data) { return true; } };
class IDataApiFactory { public: IDataApiFactory() { _export = nullptr; _import = nullptr; } virtual ~IDataApiFactory() { if (_export) { delete _export; _export = nullptr; } if (_import) { delete _import; _import = nullptr; } } bool Export(const std::string &data) { if (_export == nullptr) { _export = NewExport(); } return _export->Export(data); } bool Import(const std::string &data) { if (_import == nullptr) { _import = NewImport(); } return _import->Import(data); } protected: virtual IExport * NewExport() = 0; virtual IImport * NewImport() = 0; private: IExport *_export; IImport *_import; };
class XmlApiFactory : public IDataApiFactory { protected: virtual IExport * NewExport() { IExport * temp = new ExportXml; return temp; } virtual IImport * NewImport() { IImport * temp = new ImportXml; return temp; } };
class JsonApiFactory : public IDataApiFactory { protected: virtual IExport * NewExport() { IExport * temp = new ExportJson; return temp; } virtual IImport * NewImport() { IImport * temp = new ImportJson; return temp; } }; class TxtApiFactory : public IDataApiFactory { protected: virtual IExport * NewExport() { IExport * temp = new ExportTxt; return temp; } virtual IImport * NewImport() { IImport * temp = new ImportTxt; return temp; } };
class CSVApiFactory : public IDataApiFactory { protected: virtual IExport * NewExport() { IExport * temp = new ExportCSV; return temp; } virtual IImport * NewImport() { IImport * temp = new ImportCSV; return temp; } };
int main () { IDataApiFactory *factory = new CSVApiFactory(); factory->Import("hello world"); factory->Export("hello world"); return 0; }
|
责任链
- 使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递请求,直到有一个对象处理它为止。
- 解决的问题
- 代码结构
- 单个节点出发,实现一个处理接口,实现一个构建链表关系的静态接口
- 设计原则
- 扩展代码
举例
装饰器
- 动态地给一个对象增加一些额外的职责。就增加功能而言,装饰器模式比生产子类更为灵活。
- 解决了什么问题
- 稳定点:顺序无关地增加职责(组合的方式)
- 变化点:增加
- 设计原则
- 代码结构
- 扩展代码
举例
- 普通员工有销售奖金,累计奖金,部门经理除此之外还有团队奖金;后面可能会增加环比增长奖金,同时可能针对不同的职位产生不同的奖金组合;
- 不使用设计模式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
|
class Context { public: bool isMgr; };
class Bonus { public: double CalcBonus(Context &ctx) { double bonus = 0.0; bonus += CalcMonthBonus(ctx); bonus += CalcSumBonus(ctx); if (ctx.isMgr) { bonus += CalcGroupBonus(ctx); } return bonus; } private: double CalcMonthBonus(Context &ctx) { double bonus; return bonus; } double CalcSumBonus(Context &ctx) { double bonus; return bonus; } double CalcGroupBonus(Context &ctx) { double bonus; return bonus; } };
int main() { Context ctx; Bonus *bonus = new Bonus; bonus->CalcBonus(ctx); }
|
- 使用设计模式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
| ##include <iostream>
using namespace std; class Context { public: bool isMgr; };
class CalcBonus { public: CalcBonus(CalcBonus * c = nullptr) : cc(c) {} virtual double Calc(Context &ctx) { return 0.0; } virtual ~CalcBonus() {}
protected: CalcBonus* cc; };
class CalcMonthBonus : public CalcBonus { public: CalcMonthBonus(CalcBonus * c) : CalcBonus(c) {} virtual double Calc(Context &ctx) { double mbonus ; return mbonus + cc->Calc(ctx); } };
class CalcSumBonus : public CalcBonus { public: CalcSumBonus(CalcBonus * c) : CalcBonus(c) {} virtual double Calc(Context &ctx) { double sbonus ; return sbonus + cc->Calc(ctx); } };
class CalcGroupBonus : public CalcBonus { public: CalcGroupBonus(CalcBonus * c) : CalcBonus(c) {} virtual double Calc(Context &ctx) { double gbnonus ; return gbnonus + cc->Calc(ctx); } };
class CalcCycleBonus : public CalcBonus { public: CalcCycleBonus(CalcBonus * c) : CalcBonus(c) {} virtual double Calc(Context &ctx) { double gbnonus ; return gbnonus + cc->Calc(ctx); } };
int main() { Context ctx1; CalcBonus *base = new CalcBonus(); CalcBonus *cb1 = new CalcMonthBonus(base); CalcBonus *cb2 = new CalcSumBonus(cb1);
cb2->Calc(ctx1); Context ctx2; CalcBonus *cb3 = new CalcGroupBonus(cb1); cb3->Calc(ctx2); }
|
组合模式
- 将对象组合成树型结构以表示“部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。
- 设计原则
- 解决的问题:
- 稳定点:层次关系,对象和组合对象的使用一致性
- 变化点:对象的职责变更,组合对象里的对象变更
- 代码结构
- 使用一个接口消除叶子节点和组合对象的差异
- 维持一个容器来容纳组合对象
举例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| class IComponent { public: IComponent(); ~IComponent(); virtual void Execute() = 0; virtual void AddChild(IComponent *ele) {} virtual void RemoveChild(IComponent *ele) {} };
class Leaf : public IComponent { public: virtual void Execute() { cout << "leaf exxcute" << endl; } };
class Composite : public IComponent { private: std::list<IComponent*> _list; public: virtual void AddChild(IComponent *ele) { } virtual void RemoveChild(IComponent *ele) { } virtual void Execute() { for (auto iter = _list.begin(); iter != _list.end(); iter++) { iter->Execute(); } } };
|
2024-03-30
该篇文章被 Cleofwine
归为分类:
服务端