2 结构型模式

2021-03-02  本文已影响0人  再凌

2.1 适配器模式

把一个类的接口转化成客户希望的另外一种形式.

回调函数中需要用到的function<>绑定就是一种适配器. 原有的接口不支持, 通过适配器让其支持.

适配器有两种,

一种是类适配器, 用继承的方式实现, Adapter类继承了原来的类并实现了适配的方法.

另一种是对象适配器, 让类含有原来的类的指针/ 引用, 然后自己里面写一个方法内部转换一下接口.

2.2 桥接模式

将抽象部分与它的实现部分解耦,使得两者都能够独立变化。

例子: 对于颜色和笔头粗细, 这是不可分割的两种特性, 属于设计不当. 但是毛笔可以将水彩色和笔头粗细两种正交特性分开, 是良好的设计.

角色:

用户在持有一个抽象类的指针, 使用的时候实例化成一个扩充抽象类, 同时又可以实例化不同的具体实现类, 保证了两个方向的正交性.


桥接模式和适配器模式有什么不同? 在设计的时候使用桥接模式, 但是如果已经有了两个功能完善的类, 那么使用适配器模式.

桥接模式防止 构建抽象层和实现层过度耦合

缺点: 需要在设计的时候考虑到, 于是两者的关系建立在抽象层, 很难让以后的人识别出来

2.3 组合模式

组合多个对象形成树形结构以表示具有部分-整体关系的层次结构。组合模式让客户端可以统一对待单个对象和组合对象。

最理想的例子是树, 每次调用树的Add()方法来为他添加新的叶子节点.

组合模式有透明组合模式安全组合模式, 透明组合模式要叶子节点也实现枝子节点的方法, 如Add和delete, 但是实现是没有意义的, 因此要做异常处理; 安全组合模式让枝子节点单独去继承组合模式, 然后自己去实现管理方法, 但是这种方法大大增加了实现的复杂性.

角色有:


优点: 清晰分层次地表达对象, 让客户忽略层次差异; 符合开闭原则;
缺点: 叶子构件/ 容器构件的行为受限, 因为他们来自于相同的抽象构件, 因此如果要使用特定的方法, 那么就要在运行的时候判断对象类型.

2.4 装饰模式

动态地给一个对象增加一些额外的职责。就扩展功能而言,装饰模式提供了一种比使用子类更加灵活的替代方案。

角色:

抽象装饰类中有一个抽象构件的指针, 于是具体装饰类的run()方法中先执行具体构件, 然后再执行装饰的方法.

同样的, 这个具体装饰类还可以被传入到其他的具体装饰类中.


优点: 装饰模式比继承更加的灵活, 可以动态扩展一个对象的功能, 并且可以多次装饰
缺点: 会增加很多小的对象, 更难排错. (装饰器一直持有的是基类的指针)

2.5 外观模式

隐藏了系统内部的类和细节, 封装了一个外观给用户去调用

注意事项:

比如内部有一个用户类, 信用卡信息类, 余额类

要封装一个外观, 用户直接操作外观就可以创建一个新的储蓄账户


缺点: 增加减少子系统需要修改外观, 违反了开闭原则

2.6 享元模式

运用共享技术有效地支持大量细粒度对象的复用。

注意被共享的对象必须是细粒度的, 比如说单词池的二十六个字母, 围棋盘中的每一个围棋.

享元: 共享元数据.

享元分为外部状态和内部状态. 内部状态是不管外部怎么创建, 我的内部属性都是已知的(围棋的形状, 大小). 外部属性是根据不同的外部状况, 可能要实时改变(如围棋的位置, 黑白)

角色:


缺点: 需要区分外部状态和内部状态.

2.7 代理模式

使用代理对象来实现对原对象的访问.

为什么不直接访问? 代理有以下几个好处

  1. 远程代理: 为远程对象提供了一个本地代理, 其他程序可以直接访问这个代理.
  2. 虚拟代理: 如果创建一个真实实际对象消耗过多资源, 先创建一个代理, 等空闲的时候让代理去创建真实对象.
  3. 保护代理: 不同对象的不同访问权限.
  4. 缓冲代理: 增加一层缓冲区, 来保存这些数据(不同用户共享)
  5. 智能引用代理: 如同shared_ptr

角色有:

LOG功能就是一个代理模式. 先打印出来调用时间, 然后再真实的调用实际的函数


优点: 增加新功能时没有动抽象主题角色, 降低系统耦合度, 符合开闭原则

缺点: 让系统变慢

上一篇 下一篇

猜你喜欢

热点阅读