设计模式-结构型模式

结构型模式涉及如何组合类和对象以获得更大的结构。

Adapter(适配器)— 对象结构型模式

1.意图
将一个类的接口转换成客户希望的另一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。

2.适用性
2.1 你想使用一个已经存在的类,而它的接口不符合你的需求。
2.2 你想创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类(即那些接口可能不一定兼容的类)协同工作。
2.3 (仅适用于对象Adapter)你想使用一些已经存在的子类,但是不可能对每一个都进行子类化以匹配他们的接口。对象适配器可以适配它的父类接口。

3.结构
类适配器
在这里插入图片描述
优点:使用方便,代码简化。仅仅引入一个对象,并不需要额外的字段来引用Adaptee实例
缺点:高耦合,灵活性低。使用对象继承的方式,是静态的定义方式

对象适配器
在这里插入图片描述
优点:灵活性高、低耦合。采用 “对象组合”的方式,是动态组合方式
缺点:使用复杂。需要引入对象实例(特别是需要重新定义Adaptee行为时需要重新定义Adaptee的子类,并将适配器组合适配)。

4.参与者
4.1 Target
定义client使用的与特定领域相关的接口
4.2 Adaptee
定义一个已经存在的接口,这个接口需要适配
4.3 Adapter
对Adaptee的接口与Target接口进行适配

5.优点
5.1 更好的复用性。系统需要使用现有的类,而此类的接口不符合系统的需要。那么通过适配器模式就可以让这些功能得到更好的复用。
5.2 透明、简单。客户端可以调用同一接口,因而对客户端来说是透明的。这样做更简单 & 更直接
5.3 更好的扩展性。在实现适配器功能的时候,可以调用自己开发的功能,从而自然地扩展系统的功能。
5.4 解耦性。将目标类和适配者类解耦,通过引入一个适配器类重用现有的适配者类,而无需修改原有代码

6.缺点
6.1 过多的使用适配器,会让系统非常零乱,不易整体进行把握

Bridge(桥接)— 对象结构型模式

1.意图
将抽象部分与它的实现部分分离,使它们可以独立的变化。
2.适用性
2.1 当一个类存在两个独立变化的维度,且这两个维度都需要进行扩展时。
2.2 当一个系统不希望使用继承或者使用多层次继承使得类的个数剧增时。
2.3 当一个系统需要在构件的抽象化角色和具体化角色之间增加更多的灵活性时。
3.结构
在这里插入图片描述
4.参与者
4.1 Abstraction
定义抽象类的接口
维护一个指向Implementor类型对象的指针
4.2 RefinedAbstraction
扩充有Abstraction定义的接口
4.3 Implementor
定义实现类的接口,该接口不一定要与Abstraction接口完全一致,事实上这两个接口可以完全不同。一般来讲,Implementor接口仅提供基本操作,而Abstraction则定义了基于这些基本操作的较高层次的操作。
4.4 ConcreteImplementor
实现Implementor接口并定义它的具体实现。

5.优点
5.1 由于抽象与实现分离,所以扩展能力强;
5.2 实现细节对客户透明

6.缺点
由于聚合关系建立在抽象层,要求开发者针对抽象化进行设计与编程,这增加了系统的理解与设计难度。

Composite(组合)— 对象结构型模式

1.意图
将对象组合成树形结构以表示“部分-整体”的层次结构。Composite使得用户对单个对象和组合对象的使用具有一致性。
2.适用性
2.1 在需要表示一个对象整体与部分的层次结构的场合。
2.2 要求对用户隐藏组合对象与单个对象的不同,用户可以用统一的接口使用组合结构中的所有对象的场合。
组合模式的扩展
3.结构
组合模式分为透明方式和安全方式
透明方式
在这里插入图片描述
透明方式:在该方式中,由于抽象构件声明了所有子类中的全部方法,所以客户端无须区别树叶对象和树枝对象,对客户端来说是透明的。但其缺点是:树叶构件本来没有 Add()、Remove() 及 GetChild() 方法,却要实现它们(空实现或抛异常),这样会带来一些安全性问题。

安全方式:
在这里插入图片描述
安全方式:在该方式中,将管理子构件的方法移到树枝构件中,抽象构件和树叶构件没有对子对象的管理方法,这样就避免了上一种方式的安全性问题,但由于叶子和分支有不同的接口,客户端在调用时要知道树叶对象和树枝对象的存在,所以失去了透明性。

4.参与者
4.1 Component
它的主要作用是为树叶构件和树枝构件声明公共接口,并实现它们的默认行为。在透明式的组合模式中抽象构件还声明访问和管理子类的接口;在安全式的组合模式中不声明访问和管理子类的接口,管理工作由树枝构件完成。
4.2 Leaf
是组合中的叶节点对象,它没有子节点,用于实现抽象构件角色中 声明的公共接口。
4.3 Composite
是组合中的分支节点对象,它有子节点。它实现了抽象构件角色中声明的接口,它的主要作用是存储和管理子部件,通常包含 Add()、Remove()、GetChild() 等方法。

5.优点
5.1 组合模式使得客户端代码可以一致地处理单个对象和组合对象,无须关心自己处理的是单个对象,还是组合对象,这简化了客户端代码;
5.2 更容易在组合体内加入新的对象,客户端不会因为加入了新的对象而更改源代码

6.缺点
6.1 设计较复杂,客户端需要花更多时间理清类之间的层次关系
6.2 不容易限制容器中的构件
6.3 不容易用继承的方法来增加构件的新功能

Decorator(装饰)— 对象结构型模式

1.意图
动态的给一个对象添加一些额外的职责。就增加功能来说,装饰模式相比生成子类更灵活

2.适用性
2.1 当需要给一个现有类添加附加职责,而又不能采用生成子类的方法进行扩充时。例如,该类被隐藏或者该类是终极类或者采用继承方式会产生大量的子类。
2.2 当需要通过对现有的一组基本功能进行排列组合而产生非常多的功能时,采用继承关系很难实现,而采用装饰模式却很好实现。
2.3 当对象的功能要求可以动态地添加,也可以再动态地撤销时。

3.结构
在这里插入图片描述

4.参与者
4.1 Component
定义一个抽象接口以规范准备接收附加责任的对象。
4.2 ConcreteComponent
实现抽象构件,可以给这个对象添加一些职责
4.3 Decorator
维持一个指向Component对象的指针,并定义一个与Component接口一致的接口
4.4 ConcreteDecorator
实现Decorator的相关方法,向组件添加职责

5.优点
5.1 采用装饰模式扩展对象的功能比采用继承方式更加灵活。
5.2 可以设计出多个不同的具体装饰类,创造出多个不同行为的组合。

6.缺点
装饰模式增加了许多子类,如果过度使用会使程序变得很复杂

7.实现
JAVA I/O是此模式的最著名应用

Facede(外观)— 对象结构型模式

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

2.适用性
2.1 当客户端与多个子系统之间存在很大的联系时,引入外观模式可将它们分离,从而提高子系统的独立性和可移植性。
2.2 对分层结构系统构建时,使用外观模式定义子系统中每层的入口点可以简化子系统之间的依赖关系。
2.3 当一个复杂系统的子系统很多时,外观模式可以为系统设计一个简单的接口供外界访问。

3.结构
在这里插入图片描述
4.参与者
4.1 Facade
知道哪些子系统类负责处理请求
将客户的请求代理给适当的子系统对象
4.2 SubSystem
实现子系统的功能
处理由Facade对象指派的任务
没有Facade的任何相关信息,即没有指向Facade的指针

5.优点
5.1 降低了客户类与子系统类的耦合度,实现了子系统与客户之间的松耦合关系
5.2 外观模式对客户屏蔽了子系统组件,从而简化了接口,减少了客户处理的对象数目并使子系统的使用更加简单。
5.3 降低原有系统的复杂度和系统中的编译依赖性,并简化了系统在不同平台之间的移植过程

6.缺点
6.1 在不引入抽象外观类的情况下,增加新的子系统可能需要修改外观类或客户端的源代码,违背了“开闭原则”
6.2 不能很好地限制客户使用子系统类,如果对客户访问子系统类做太多的限制则减少了可变性和灵活性。

Flyweight(享元)— 对象结构型模式

1.意图
运用共享技术有效的支持大量细粒度对象

2.适用性
当以下情况都成立时使用享元模式
2.1 一个程序使用了大量的对象
2.2 完全由于使用大量的对象造成很大的存储开销
2.3 对象的大多数状态都可变为外部状态
2.4 如果删除对象的外部状态,那么可以用相对较少的共享对象取代很多组对象。
2.5 应用程序不依赖于对象标识。

3.结构
在这里插入图片描述

4.参与者
4.1 Flyweight
是所有的具体享元类的基类,为具体享元规范需要实现的公共接口,非享元的外部状态以参数的形式通过方法传入。
4.2 ConcreteFlyweight
实现抽象享元角色中所规定的接口。
4.3 UnsharableFlyweight
是不可以共享的外部状态,它以参数的形式注入具体享元的相关方法中。
4.4 FlyweightFactory
负责创建和管理享元角色。当客户对象请求一个享元对象时,享元工厂检査系统中是否存在符合要求的享元对象,如果存在则提供给客户;如果不存在的话,则创建一个新的享元对象。

5.优点
相同对象只要保存一份,这降低了系统中对象的数量,从而降低了系统中细粒度对象给内存带来的压力。

6.缺点
6.1 为了使对象可以共享,需要将一些不能共享的状态外部化,这将增加程序的复杂性。
6.2 读取享元模式的外部状态会使得运行时间稍微变长。

Proxy(代理)— 对象结构型模式

1.意图
为其他对象提供一种代理以控制对这个对象的访问

2.适用性
2.1 远程代理,这种方式通常是为了隐藏目标对象存在于不同地址空间的事实,方便客户端访问。例如RPC
2.2 虚拟代理,这种方式通常用于要创建的目标对象开销很大时。例如,下载一幅很大的图像需要很长时间,因某种计算比较复杂而短时间无法完成,这时可以先用小比例的虚拟代理替换真实的对象,消除用户对服务器慢的感觉。
2.3 安全代理,这种方式通常用于控制不同种类客户对真实对象的访问权限。
2.4 智能指引,主要用于调用目标对象时,代理附加一些额外的处理功能。例如,增加计算真实对象的引用次数的功能,这样当该对象没有被引用时,就可以自动释放它。
2.5 延迟加载,指为了提高系统的性能,延迟对目标的加载。例如,Hibernate 中就存在属性的延迟加载和关联表的延时加载。

3.结构
在这里插入图片描述

4.参与者
4.1 Subject
通过接口或抽象类声明真实主题和代理对象实现的业务方法。
4.2 RealSubject
实现了抽象主题中的具体业务,是代理对象所代表的真实对象,是最终要引用的对象。
4.3 Proxy
提供了与真实主题相同的接口,其内部含有对真实主题的引用,它可以访问、控制或扩展真实主题的功能。

5.优点
5.1 代理模式在客户端与目标对象之间起到一个中介作用和保护目标对象的作用;
5.2 代理对象可以扩展目标对象的功能;
5.3 代理模式能将客户端与目标对象分离,在一定程度上降低了系统的耦合度;

6.缺点
6.1 在客户端和目标对象之间增加一个代理对象,会造成请求处理速度变慢;
6.2 增加了系统的复杂度;

总结

Adapter模式和Bridge模式具有一些共同的特征。他们都给另一对象提供了一定程度的间接性,因为有利于系统的灵活性。它们都涉及从自身以外的一个接口向这个对象转发请求。Adapter模式主要是为了解决两个已有接口的不匹配问题。Bridge模式则对抽象接口与它的(可能是多个)实现部分进行桥接。由于这些不同点,当你发现两个不兼容的类必须同时工作时,就有必要使用Adapter模式。相反,Bridge使用者必须事先知道:一个抽象将有多个实现部分,并且抽象和实现两者是独立演化的。

Composite模式和Decorator模式具有类似的结构图,说明他们都基于递归组合来组织可变数目的对象。Decorator模式旨在使你不需要生成子类即可给对象添加职责。这就避免了静态实现所有功能的组合,从而导致子类急剧增加。Composite它旨在构造类,使多个相关的对象能够以统一的方式处理,而多个对象可以被当作一个对象来处理。它的重点不在于修饰,而在于表示。从Decorator模式角度看,Composite是一个ConcreteComponent。而从Composite模式的角度看,Decorator是一个leaf。

另一个与Decorator模式相似的是Proxy。这两种模式都描述了怎样为对象提供一定程度上的间接引用。像Decorator一样,Proxy构成一个对象并为用户提供一致的接口。但Proxy不能动态的添加和分离性质,它也不是尾递归组合而实际的,它的目的是当直接访问一个实体不方便时或不符合需求时,为这个实体提供一个替代者。

在Decorator模式中,组件仅提供了部分功能,而一个或者多个Decorator负责完成其他功能。Decorator模式适用于编译时不能(至少不方便)确定对象的全部功能的情况。这种开放性使递归组合成为Decorator模式中一个必不可少的部分。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值