美文网首页
2 结构型模式

2 结构型模式

作者: 再凌 | 来源:发表于2021-03-02 13:28 被阅读0次

    2.1 适配器模式

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

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

    适配器有两种,

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

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

    2.2 桥接模式

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

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

    角色:

    • 抽象类: 定义抽象接口, 抽象类中有一个实现类接口的指针
    • 实现类接口:抽象定义另外一个维度
    • 扩充抽象类: 定义抽象类实现的接口
    • 具体实现类: 实现了"实现类接口"定义的接口

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


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

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

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

    2.3 组合模式

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

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

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

    角色有:

    • 抽象构件(定义了一些公共接口, 叶子构件和容器构件都要实现)
    • 叶子构件
    • 容器构件(里面可以有容器构件, 也可以是叶子构件)

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

    2.4 装饰模式

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

    角色:

    • 抽象构件:; 是具体构件和装饰类的共同基类, 定义了run()方法
    • 具体构件: 继承自抽象构件
    • 抽象装饰类: 继承自抽象构件
    • 具体装饰类: 实现了抽象装饰类的方法

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

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


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

    2.5 外观模式

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

    注意事项:

    • 不要增加额外的功能
    • 不要返回内部子系统的组件给客户, 但是必要的时候提供native_handle方法给客户
    • 外观模式的目的是提供一个高层次的接口, 所以不要进行低层次的单独业务执行

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

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


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

    2.6 享元模式

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

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

    享元: 共享元数据.

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

    角色:

    • 享元工厂: 创建享元, 同时还可以预先创造出享元池, 到时候直接给出
    • 抽象享元
    • 具体享元

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

    2.7 代理模式

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

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

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

    角色有:

    • 抽象主题角色: 声明了代理和真实主题角色的共同接口, 客户端是针对抽象主体角色编程的.
    • 代理主题角色: 在抽象主体的基础上, 还可以实现一些新的功能, 同时保存了一个真实主题角色的指针(其实保存一个抽象主体角色的指针也行).
    • 真实主题角色: 实现了抽象主题角色的接口

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


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

    缺点: 让系统变慢

    相关文章

      网友评论

          本文标题:2 结构型模式

          本文链接:https://www.haomeiwen.com/subject/flsgfltx.html