Java设计模式-结构型模式

文章目录

  • 前言
  • 适配器模式(Adapter Pattern)
  • 桥接模式(Bridge Pattern)
  • 组合模式(Composite Pattern)
  • 外观模式(Facade Pattern)
  • 装饰模式(Decorator Pattern)
  • 代理模式(Proxy Pattern)
  • 总结


前言

本博客仅做学习笔记,如有侵权,联系后即刻更改

科普:


适配器模式(Adapter Pattern)

定义

将一个类的接口转换成客户希望的另一个接口,适配器模式让那些接口不兼容的类可以一起工作
又称为包装器(Wapper)模式,这里的接口未指的是广义接口(一个方法或者方法的集合)

类适配器模式

继承Adaptee类 + 实现Target接口

  • 缺点
    只能适配一个适配者类,且该类不能为最终类
    目标类只能为接口
    Java设计模式-结构型模式_第1张图片

对象适配器

继承Target类 + 关联Adaptee类

  • 缺点
    置换适配者类麻烦
    Java设计模式-结构型模式_第2张图片

缺省适配器模式(Default Adapter Pattern)

它适用于不想使用一个接口中的所有方法的情况

  • 又称为单接口适配器模式。
    当不需要实现一个接口所提供的所有方法时,可先设计一个抽象类实现该接口,并为接口中每个方法提供一个默认实现(空方法),那么该抽象类的子类可以选择性地覆盖父类的某些方法来实现需求

模式优点

  • 将目标类和适配者类解耦,通过引入一个适配器类来重用现有的适配者类,无须修改原有结构
  • 增加了类的透明性和复用性,提高了适配者的复用性,同一个适配者类可以在多个不同的系统中复用
  • 灵活性和扩展性非常好
  • 类适配器模式:置换一些适配者的方法很方便
  • 对象适配器模式:可以把多个不同的适配者适配到同一个目标,还可以适配一个适配者的子类

适配者模式适用环境

  • 系统需要使用一些现有的类(适配者),而这些类的接口不符合系统的需要甚至没有这些类的源代码
  • 创建一个可以重复使用的类(目标类/适配者),用于和一些彼此之间没有太大关联的类,包括一些可能在将来引进的类一起工作

桥接模式(Bridge Pattern)

定义

将抽象部分和它的实现部分解耦,使得两者可以独立变化

  • 又称为柄体模式或接口描述,常见有蜡笔毛笔问题

包含的角色

  • Abstraction(抽象类)
  • RefinedAbstraction(扩充抽象类)
  • Implementor(实现类接口)
  • ConCreteImplementor(具体实现类)
    Java设计模式-结构型模式_第3张图片

桥接模式优点

  • 分离抽象接口及其实现部分
  • 可以取代多层继承方案,极大地减少了子类的个数
  • 提高了系统的可扩展性,在两个变化维度中任意扩展一个维度,不需要修改原有系统,符合开闭原则

缺点

  • 会增加系统的理解与设计难度,由于关联关系建立在抽象层,要求开发者一开始就针对抽象层进行设计与编程
  • 正确识别出系统中两个独立变化的维度并不是一件容易的事情

适用环境

  • 需要在抽象化和具体化之间增加更多的灵活性,避免在两个层次之间建立静态的继承关系
  • 抽象部分和实现部分可以以继承的方式独立扩展而互不影响
  • 一个类存在两个(或多个)独立变化的维度,且这两个(或多个)维度都需要独立地进行扩展
  • 不希望使用继承或因为多层继承导致系统类的个数急剧增加的系统

组合模式(Composite Pattern)

定义

组合多个对象形成树形结构以表示具有部分-整体关系的层次结构

  • 组合模式让客户端可以统一对待单个对象和组合对象
    Java设计模式-结构型模式_第4张图片

角色

  • Component(抽象构件)
  • Leaf(叶子构件)
  • Composite(容器构件)

透明组合模式

抽象组件声明所有管理成员对象的方法

  • 客户端可以一致对待所有对象
  • 不够安全,叶子对象和容器对象本质上有区别
    Java设计模式-结构型模式_第5张图片
    安全组合模式
  • 对于叶子对象,客户端不可能调用到这些方法
  • 缺点是不够透明,客户端不能完全针对抽象编程,必须有区别地对待叶子构件和容器构件

模式分析

优点

  • 可以清楚地定义分层次的复杂对象,表示对象的全部或部分层次,让客户端忽略了层次的差异,方便对整个层次结构进行控制
  • 客户端可以一致地使用一个组合结构或其中单个对象,不必关心处理的是单个对象还是整个组合结构,简化了客户端代码
  • 增加新的容器构件和叶子构件都很方便,符合开闭原则
  • 为树形结构的面向对象实现提供了一种灵活的解决方案

缺点

  • 在增加新构件时很难对容器中的构件类型进行限制

适用场景

  • 在具有整体和部分的层次结构中,希望通过一种方式忽略整体与部分的差异,客户端可以一致地对待它们
  • 在一个使用面向对象语言开发的系统中需要处理一个树形结构
  • 在一个系统中能够分离出叶子对象和容器对象,而且它们的类型不固定,需要增加一些新的类型

外观模式(Facade Pattern)

定义

为子系统中的一组接口提供一个统一的入口。外观模式定义了一个高层接口,这个接口使得子系统更加容易使用

  • 门面模式,是对迪米特法则的具体实现
  • 通过引入一个新的外观角色来降低原有系统的复杂度,同时降低客户类与子系统之间的耦合度
  • 所指的子系统是一个广义的概念,它可以是一个类、一个功能模块、系统的一个组成部分或者一个完整的系统
    Java设计模式-结构型模式_第6张图片
    角色
  • Facade (外观角色)
  • SubSystem(子系统角色)

抽象外观类

动机

  • 在标准的外观模式结构图中,如果需要增加、删除或更换与外观类交互的子系统类,必须修改外观类或客户端的源代码,这将违背开闭原则

模式分析

优点

  • 对客户端屏蔽了子系统组件,减少了客户端所需处理的对象数目,并使得子系统使用起来更加容易
  • 实现了子系统与客户端之间的松耦合关系,这使得子系统的变化不会影响到调用它的客户端,只需要调整外观类即可
  • 子系统的内部变化不会影响到外观对象,一个子系统的修改对其他子系统也没有任何影响

缺点

  • 不能很好地限制客户端直接使用子系统类,如果对客户端访问子系统类做太多的限制则减少了可变性和灵活性
  • 如果设计不当,增加新的子系统可能需要修改外观类的源代码,违背了开闭原则

适用环境

  • 要为访问一系列复杂的子系统提供一个简单入口
  • 客户端程序与多个子系统之间存在很大的依赖性
  • 在层次化结构中,可以使用外观模式来定义系统中每一层的入口,层与层之间不直接产生联系,而是通过外观类建立联系,降低层之间的耦合度

装饰模式(Decorator Pattern)

定义

动态地给一个对象增加一些额外的职责,就增加对象功能来说,装饰模式比生成子类实现更为灵活

角色

  • Component: 抽象构件类
  • ConcreteComponent:具体构件类
  • Decorator:抽象装饰类
  • ConcreteDecorator:具体装饰类
    Java设计模式-结构型模式_第7张图片

透明装饰模式

对象声明全为抽象构件

优点

  • 对于客户端而言,具体构件和具体装饰对象没有区别
  • 可以多层次装饰

缺点

  • 无法在客户端单独调用新增具体装饰层的方法
    Java设计模式-结构型模式_第8张图片

半透明装饰模式

优点

  • 具体装饰类型定义装饰后的对象,具体构件使用抽象构件类型定义
  • 客户端使用具体装饰类型来定义装饰后的对象
    可以单独调用具体装饰类的新增方法

缺点
不能实现对同一个对象的多次装饰,显示的是最后一次装饰的样式
Java设计模式-结构型模式_第9张图片

模式优缺点分析

优点

  • 动态增加对象的功能,使用关联降低耦合
  • 具体构建类和具体装饰类独立变化,符合开闭原则

缺点

  • 会产生很多小对象,占用系统资源,影响系统性能
  • 排错较难,对于多次装饰对象,需要逐级排查

适用场景

  • 动态透明给单个对象增添职责
  • 当继承无法满足对系统扩展或维护的需求

代理模式(Proxy Pattern)

定义

给某一个对象提供一个代理或占位符,并由代理对象来控制对原对象的访问

  • 符合开闭原则
  • 应用场景:快捷方式
    Java设计模式-结构型模式_第10张图片
    包含的角色
    Subject(抽象主题角色)
    Proxy (代理主题角色)
    Subject(抽象主题角色)Proxy (代理主题角色)

代理模式分类

远程代理

  • 远程代理(Remote Proxy):为一个位于不同的地址空间的对象提供一个本地的代理对象,这个不同的地址空间可以在同一台主机中,也可以在另一台主机中,远程代理又称为大使(Ambassador)
  • 例如Java中的RMI

虚拟代理

  • 虚拟代理(Virtual Proxy):如果需要创建一个资源消耗较大的对象,先创建一个消耗相对较小的对象来表示,真实对象只在需要时才会被真正创建
  • 例如使用小图先代替大图显示

保护代理

  • 控制对一个对象的访问,可以给不同的用户提供不同级别的使用权限

缓冲代理

  • 为某一个目标操作的结果提供临时的存储空间,以便多个客户端可以共享这些结果
  • 例如petshop(.net)/petstore(java)

智能引用代理

  • 当一个对象被引用时,提供一些额外的操作,例如将对象被调用的次数记录下来等

模式分析

共有优点

  • 能够协调调用者和被调用者,在一定程度上降低了系统的耦合度
  • 客户端可以针对抽象主题角色进行编程,增加和更换代理类无须修改源代码,符合开闭原则,系统具有较好的灵活性和可扩展性

特有优点

  • 远程代理:
    可以将一些消耗资源较多的对象和操作移至性能更好的计算机上提高了系统的整体运行效率
  • 虚拟代理:
    通过一个消耗资源较少的对象来代表一个消耗资源较多的对象,可以在一定程度上节省系统的运行开销】
    缓冲代理:
    为某一个操作的结果提供临时的缓存存储空间,以便在后续使用中能够共享这些结果,优化系统性能,缩短执行时间
    保护代理:
    可以控制对一个对象的访问权限,为不同用户提供不同级别的使用权限

适用环境

  • 当客户端对象需要访问远程主机中的对象时可以使用远程代理
  • 当需要用一个消耗资源较少的对象来代表一个消耗资源较多的对象,从而降低系统开销、缩短运行时间时可以使用虚拟代理
  • 当需要为某一个被频繁访问的操作结果提供一个临时存储空间,以供多个客户端共享访问这些结果时可以使用缓冲代理
  • 当需要控制对一个对象的访问,为不同用户提供不同级别的访问权限时可以使用保护代理
  • 当需要为一个对象的访问(引用)提供一些额外的操作时可以使用智能引用代理

总结

小小励志

有些事你现在不做,一辈子都不会做了。
如果你想做一件事,全世界都会为你让路。
《搭车去柏林》

你可能感兴趣的:(#,设计模式,java,设计模式,开发语言)