文章目录
面向对象设计之设计模式(结构型篇)
主要用于如何组合已有的类和对象来获得更大的结构,它采用继承机制来组合接口或实现,以提供统一的外部视图或新的功能
适配器模式(Adapter)
将一个类的接口,转换成客户期望的另一个接口,适配器让原本不兼容的类可以合作无间
优点
- 允许两个或多个不兼容的对象进行交互和通信
- 提高已有功能的重复使用性
- 增加了类的透明度
- 灵活性好
缺点
- 过多的使用适配器会让系统非常零乱,不易整体进行把握
适用场景
- 要使用已有的类,而该类接口与所需要的接口并不匹配
- 要创建可复用的类,该类可以与不相干或未知类进行协助,即类之间不需要兼容接口
- 要在一个不同于已知对象接口的接口环境中使用对象
- 必须要进行多个源之间接口转换的时候
桥接模式(Bridge)
将一个辅助的组建分成两个独立的但又想管的继承层次结构,功能性的抽象和内部实现
桥接模式的左边为功能的类层次,右边为实现的类层次
优点
- 可以将接口与实现相分离
- 提高可扩展性
- 对客户隐藏了实现的细节
缺点
- 增加了系统的理解和设计难度
- 要求正确识别出系统中两个独立变化的维度,因此其使用范围有一定的局限性
适用场景
- 想避免在抽象及其实现之间存在永久的绑定
- 抽象及其实现可以使用子类进行扩展
- 抽象的实现被改动应该对客户端没有影响
组合模式(Composite)
允许你将对象组合成树形结构来表现“整体/部分”层次结构。组合能让客户以一致的方式处理个别对象以及对象组合
可以类比到 Java 中关于文件和文件夹的特性
组合和迭代器一起使用,能够达到便利组建内部细节的目的
优点
- 清楚地定义分层次的复杂对象,表示对象的全部或部分层次
- 是的增加新构件更容易
- 提高了结构的灵活性和可管理的接口
缺点
- 是设计变得更加抽象,如果对象的业务规则很复杂,则实现组合模式有很大的挑战性,而且不是所有的方法都叶子对象有关联
适用场景
- 想表示对象的部分/整体层次结构
- 希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象
- 结构可以具有任何级别的复杂性,而且是动态的
装饰模式(Decorator)
动态地给对象增加一些额外的责任,就增加功能来说,装饰比生成子类更为灵活
优点
- 比静态继承具有更大的灵活性
- 简化代码
- 改进对象扩展性,用户可以通过编写新的类来做出改变
- 装饰类和被装饰类可以独立发展,不会相互耦合
缺点
- 多层装饰比较复杂
适用场景
- 想要在单个对象中动态并且透明地增加责任
- 想要在以后可能要修改的对象中添加责任
- 当无法通过静态子类化扩展时
外观模式(Facade)
提供了一个统一的接口,用来访问子系统中的一群接口。外观模式定义了一个高层接口,让子系统更容易使用
优点
- 在不减少系统所提供的选项的情况下,为复杂系统提供了简单的接口
- 对客户端屏蔽了系统组件
- 提高了子系统与其客户端之间的弱耦合度
- 激情客户端请求转换后发送给能够处理这些请求的子系统
缺点
- 不能很好地限制客户使用子系统类,如果对客户访问子系统类做太多的限制,则减少了可变性和灵活性
- 在不引入抽象外观类的秦光下,增加新的子系统可能需要修改外观类或客户端的源代码,违背了“开闭原则”
适用场景
- 为一个复杂子系统提供一个简单的接口时
- 客户程序与抽象类的实现部分之间存在着很大的依赖性
- 构件一个层次结构的子系统时,使用 Facade 模式定义子系统中每层的入口点,如果子系统之间是相互依赖的,你可以让他们仅通过 Facade 进行通信,从而简化他们之间的依赖关系
享元模式(Flyweight)
通过共享对象减少系统中低等级的、详细的对象数目
优点
- 减少要处理的对象数目
- 如果对象能够持续,可以减少内存和存储设备
缺点
- 是的应用程序在某种程度上来说更加复杂化了
- 为了使对象可以共享,享元模式需要将享元对象的状态外部化,而读取外部状态使得运行时间变长了
使用场景
- 应用程序使用大量的对象
- 由于对象数目巨大,导致很高的存储开销
- 应用程序不依赖于对象的身份
代理模式(Proxy)
为控制对出事对象的访问,提供了一个代理或者占位符对象
代理分类:
- Virtual Proxy:虚拟代理,知道需要用到对象实例时,踩产生或进行初始化
- Remote Proxy:远程代理
- Access Proxy:访问代理,这个代理只限已经登陆的用户才能调用的方法
优点
- 远程代理可以隐藏对象位于不同的地址空间的事实
- 虚拟代理可以执行优化操作
缺点
- 请求的处理速度变慢
- 实现代理模式需要额外的工作,从而增加了系统实现的复杂度
使用场景
- 当需要为一个对象在不同的地址空间提供局部的代表时
- 当需要创建开销非常大的对象时