结构型模式 ######################################## 这些设计模式关注类和对象的组合。继承的概念被用来组合接口和定义组合对象获得新功能的方式。 适配器模式 **************************************** 适配器的作用为:``将一个类的接口转换成客户希望的另外一个接口,适配器使得原本由于接口不兼容而不能一起工作的那些类可以一起工作`` 适配器主要应用于希望复用一些现存的类,但是接口又与复用环境要求不一致的情况。其分为两种:类适配器和对象适配器模式: - 类适配器使用 ``继承`` 来适配接口 - 对象适配器使用 ``组合`` 来适配接口 例如: .. code-block:: cpp class Voltage{ // 中国的通用电压是 220V size_t voltage = 220; public: size_t output(){ return this->voltage; } }; bool PhoneCharging(size_t voltage){ // 手机充电需要的电压一般为 5V static size_t phone_voltage = 5; if( voltage == phone_voltage) return true; return false; } class ClassAdapter: Voltage{ public: size_t adapter(){ size_t voltage = Voltage::output()/44; // 对通用电压进行转换 return voltage; } }; class ObjectAdapter{ Voltage vol; public: size_t adapter(){ return vol.output()/44; } }; // 使用 ClassAdapter classAdapter; ObjectAdapter objectAdapter; cout< children; const char* _name; public: explicit Root(const char* name) : _name(name){} const char * name() override{ return _name; } Node * add(Node* child) override{ children.push_back(child); return child; } void display() override{ cout<<_name<display(); } } }; class Leaf: public Node{ const char* _name; public: explicit Leaf(const char* name): _name(name){} const char * name() override{ return _name; } Node * add(Node *) override{ return nullptr; } // 叶节点没有孩子 void display() override{ cout<<"-"<<_name<add(new Leaf("first_leaf")); first->add(new Leaf("first_leaf2")); root.display(); // 通过根节点操纵所有孩子 结果: .. code-block:: root -first --first_leaf --first_leaf2 -second 装饰器模式 **************************************** 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。 这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。 装饰器动态地给一个对象添加一些额外的职责。就增加功能来说,装饰器模式相比生成子类更为灵活。其用法类似与组合,但是相比组合,导出的接口更少。 例如:[#]_ .. code-block:: cpp class Pancake{ public: virtual const string description() = 0; virtual int cost() = 0; }; class MeatPancake : public Pancake{ const string name = "肉煎饼"; public: const string description() override{ return name; } int cost() override{ return 1; } }; class PancakeDecorator: public Pancake{ Pancake* decorated; public: explicit PancakeDecorator(Pancake* cake): decorated(cake){} const string description() override{ return decorated->description(); } int cost() override{ return decorated->cost(); } virtual ~PancakeDecorator() = 0{ } }; class Egg: public PancakeDecorator{ public: explicit Egg(Pancake* cake): PancakeDecorator(cake){} const string description() override{ return PancakeDecorator::description() + "加蛋"; } int cost() override{ return PancakeDecorator::cost() + 1.5; } }; class Potato: public PancakeDecorator{ public: explicit Potato(Pancake* cake): PancakeDecorator(cake){} const string description() override{ return PancakeDecorator::description() + "加土豆"; } int cost() override{ return PancakeDecorator::cost() + 2; } }; // Pancake *cake = new MeatPancake; cake = new Egg(cake); cake = new Potato(cake); cout << cake->description() << endl << cake->cost(); 你可能会发现,实际上这是一种“横向类型转换”,为了保证代码的正确性,所有被访问的接口必须是虚有的,因此通过装饰器的基类来限定可访问的接口,并做为子类做一些初始化工作。 外观模式 **************************************** 外观模式:为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。 .. code-block:: cpp class SubSystemOne { public: void MethodOne() { cout << "MethodOne" << endl; } }; class SubSystemTwo { public: void MethodTwo() { cout << "SubSystemTwo" << endl; } }; class Facade { SubSystemOne one; SubSystemTwo two; public: void MethodA() { one.MethodOne(); } void MethodTwo() { two.MethodTwo(); } }; // 使用 Facade facade; facade.MethodA(); facade.MethodTwo(); 享元模式 **************************************** 享元模式用于创建大量重复的对象,比如围棋棋子,通过区分其常用状态(内部状态)和不常用状态(外部状态)将其进行划分。 .. code-block:: cpp typedef pair Coords; enum class Color { black, white }; class Go { Color color; vector coords; public: Go(Color color): color(color){} void setCoords(Coords coord) { coords.push_back(coord); } }; class GoFactory { unordered_map gos; public: Go getGo(Color color) { if (gos.find(color) == gos.end()) { Go go(color); gos.insert(pair(color, go)); } return gos.at(color); } }; // 使用 GoFactory factory; auto white = factory.getGo(Color::white); white.setCoords(Coords(10,20)); white.setCoords(Coords(10,25)); white.setCoords(Coords(10, 30)); auto black = factory.getGo(Color::black); black.setCoords(Coords(5,15)); black.setCoords(Coords(5,25)); black.setCoords(Coords(5,35)); 代理模式 **************************************** 代理模式用于为其他对象提供一种代理以控制这个对象的访问。主要用途有: - 远程代理:为远程对象提供本地代理,以提供在本地访问的方法 - 虚拟代理:根据需要创建开销很大的对象,通过代理储存真实对象 - 安全代理:用于控制访问真实对象时的权限 - 智能引用:比如智能指针 .. [#] Effective C++ 第三版 条款31:将文件间的编译依赖依存关系降到最低 .. [#] `装饰器模式(Decorator) C++ - luStar - 博客园 `_