设计模式之结构型模式
Posted 求知若饥虚心若愚,脚着沃野长望星空,天高海阔水静深流.
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式之结构型模式相关的知识,希望对你有一定的参考价值。
一、结构型模式概述
结构型模式描述了如何组合类和对象以构成更大的结构。
结构型类模式主要描述了类与类之间如何组合以构成更大的结构,而类与类之间主要通过继承的方式组合接口和实现。
结构型对象模式主要描述对象与对象之间如何组合以构成更大的结构,对象与对象之间通过组合和聚合的方式实现组合。因为它可以在运行时改变对象之间的组合关系,具有更大的灵活性。
1、继承与组合
(1)继承:
对象的继承关系在编译时期就已经确定了,运行时是无法改变的。通过继承建立的父子关系,对象与对象之间实现了代码的复用也实现了父类与子类的紧密的依赖关系。父类中的任何变化都会引起子类的变化,限制了子类的灵活性和复用性。
(2)组合/聚合
根据合成/聚合复用原则,尽量使用合成/聚合,尽量不要使用类继承。聚合表示一种弱的“拥有”关系,合成表示一种强的关系,体现了严格的局部与整体的关系。使用合成/聚合复用原则的好处是,优先使用对象的合成/聚合将有利于保持每个类被封装,并被集中在单个任务上。这样类和类继承层次都会保持比较小的规模,不会造成类膨胀,不太可能造成类增长为不可控制的庞然大物。
二、结构型模式内容
1、适配器模式
(1)功能:
将一个类的接口转换成客户希望的另外一个接口,使得原本接口不兼容而不能一起工作的那些类可以一起工作。
安装客户需求的接口复用现有一个接口使得现有的接口可以与不兼容的接口一起工作
(2)适用性:
1)想要复用现有的一个类,但是它的接口又不符合要求时。或者两个类之间不兼容不匹配的时候使用。
2)想要创建一个可以复用的类,该类可以与其他不相关的类或者不可预见的类协同工作(即可以与不兼容接口进行协同)
(3)结构
(4)参与者
Target:目标需求,定义Client使用的与特定领域相关的接口
Client:客户端要求与Target接口的对象协同
Adaptee:定义一个已经存在的类,即要复用的类。也就是需要适配器的接口
Adapter:实现Target接口继承Adaptee类,在Target接口方法Request()中调用父类Adaptee的SpecificRequest()方法,实现包装调用。
(5)优缺点
(6)相关模式
1)桥接模式:
与桥接模式类似,但是出发点不同。桥接模式的目的是将接口部分和实现部分分离,从而对它们可以较为容易也相对独立的加以改变。
而适配器模式:意味着改变一个已有对象的接口
2)装饰模式:
装饰模式增强了其他对象的功能而同时又不改变它的接口。装饰模式对应用程序的透明性比适配器要好。且支持递归组合
纯粹使用适配器不可能实现这一点
3)代理模式:
在不改变它的接口条件下,为另一个对象定义了代理。
2、桥接模式
(1)功能
将抽象部分与它的实现部分分离,使它们都可以独立地变化
实现系统可能有多角度分类,每一种分类都有可能变化,那么就把这种多角度分离出来的让它们独立变化,减少它们之间的耦合度。
(2)适用条件
1)不希望抽象部分与实现部分过度耦合
2)实现部分的修改对客户不产生影响,即客户的代码不用重新编译
3)向客户完全隐藏实现部分
4)为避免使用继承造成增加大量的类,且不能满足开放-封闭原则的情况下使用桥接模式
5)当一个抽象有多个实现的时候,需要分离抽象部分和实现部分
6)当一个类存在两个独立变化的维度,且这两个维度都需要进行扩展时。
7)当一个系统需要在构件的抽象化角色和具体化角色之间增加更多的灵活性时。
(3)结构
(4)参与者
Implementor:具体实现的接口,定义实现类的接口
ConcreteImplementor:实现Implementor的负责具体实现的类
Abstractor:抽象部分的接口。定义抽象类的接口
RefinedAbstractor:扩充由Abstractor定义的接口
(5)优缺点
1)优点:a.提高可扩展性;b.实现细节对客户透明
2)缺点:
(6)相关模式
1)抽象工厂模式:
桥接模式可以用抽象工厂模式创建和配置一个特定的桥接模式
2)适配器模式:
用来帮助无关类的协同工作,一般是在系统完成设计后才会使用
而桥接模式使在系统设计开始的时候就开始使用,它的抽象部分和实现部分可以独立的进行改变。
3、组合模式
(1)功能
将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性
描述了如何构造一个类层次式结构,这一结构有两种类型的对象(基元对象和组合对象)所对应的类型构成。
(2)适用条件
1)想要体现部分与整体的层次结构的时候
2)希望用户忽略组合对象和单个对象的不同,统一的使用组合结构中的所有对象时候
(3)结
(4)参与者
Componet:表示组合中的对象的接口,提供访问和管理子部件的接口。适当的情况下,可以对共有的接口提供默认实现
Leaf:表示组合中没有子节点的叶子节点,实现Component接口。但是不具体实现访问和管理字节的接口,因为它没有子节点
Composite:表示组合中具有子节点且实现Component接口的对象,实现了Component接口中定义的访问和操作子部件的接口。
(5)优缺点
1)优点:
a.简化客户代码
b.更容易增加新类型的组件
2)缺点:很难显示组合中的组件
(6)相关模式
1)责任链模式: 通常部分-父部件连接用于责任链模式
2)装饰模式:装饰模式和组合模式一起搭配使用。他们具有一个公共的父类,装饰类必须支持具有Add,Remove,getChild操作的Component
3)享元模式:享元模式让你共享组件,但是不再能引用他们的父部件
4)迭代器模式:用来遍历组合模式
5)访问者模式:将本来应该分布在Composite和Leaf中的操作和行为局部化。
4、装饰模式
(1)功能
在不改变现有对象结构的情况下,动态的给一个对象增加额外的职责,就增加功能来讲,装饰模式比生成子类更为灵活
(2)适用条件
1)在不影响其他对象的情况下,以动态,透明的方式给单个对象添加职责
2)处理那些可以撤销的职责
3)需要区分核心职责和装饰功能的时候
(3)结构
当只有一个ConcreteComponent类而没有Component的时候,那么Decorator类可以是ConcreteComponent的一个子类。
同理,如果只有一个ConcreteDecorator那么就没有必要创建一个单独的Decorator类,而可以吧Decorator和ConcreteDecorator的责任合并层一个类。
(4)参与者
Conponent:定义一个对象的接口,就是需要装饰的类,即装饰的目标类
ConcreteComponent:定义一个具体的对象,也可以被装饰。在只有一个ConcreteComponent的情况下,不需要实现Component接口,直接将ConcreteComponent作为Decorator的父类
Decorator:装饰抽象类
ConcretorDecorator:具体的装饰类,实现Decorator接口
(5)优缺点
1)优点:a.将类中的装饰功能从类中搬移去除,简化原有的类
b.有效的将核心职责和装饰功能区分开了,而且可以去除相关重复的装饰逻辑
(6)相关模式
1)装饰模式与适配器模式:
装饰模式仅改变对象的职责而不改变它的接口,而适配器模式将给对象一个全新的接口。
2)装饰模式与组合模式:
装饰模式的目的不是在聚集,装饰模式可以视为一个退化的,仅有一个组件的组合。
相同点:组合模式和装饰模式都是基于递归组合来组织可变数据的对象
区别:装饰模式旨在不通过继承添加子类的方式给指定对象增加职责。重点在于装饰
组合模式旨在构造类,使多个相关的对象可以以统一的方式处理,而多重对象可以被当中一个对象来处理重点在于表示
搭配使用:组合模式+装饰模式
Decorator和Component实现于同一个接口,
从组合模式看:Decorator相当于组合模式内的Leaf,而Component相当于一个复合对象的Composite
从装饰模式看:Component相当于一个ConcretePonent,而Decorator相当于Decorator
3)装饰模式与策略模式:
装饰模式改变的是对象的外表,而策略模式改变的是对象的内核。改变对象的两种途径:装饰模式,策略模式
5、外观模式
(1)功能
为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用
(2)适用条件
1)需要为一个复杂的子系统提供一个简单接口时
2)客户端与抽象的具体实现存在很大的依赖的的时候,引入Facade实现客户端与子系统解耦、分离,提供子系统的独立性和可移植性。
3)当需要构建一个层次结构的子系统,子系统之间彼此分离降低依赖,使用Facade定义子系统中每层的入口点。
(3)结构
(4)参与者
Facade:外观类,知道哪些子系统类负责处理请求。将客户的请求代理给适当的子系对象。
SubSystem:表示子系统中的一组接口。实现子系统中的功能,处理有Facade对象指派的任务,没有任何Facademic对象的引用
(5)优缺点
1)对客户屏蔽了子系统,减少了客户需要处理对象的数目并使得子系统使用起来更加方便
2)实现客户与子系统的松耦合关系,有助于建立层次结构系统,也有助于对对象之间的依赖关系分成。可以消除复杂的循环依赖问题
(6)相关模式
1)抽象工厂:抽象工厂可以和外观模式一起搭配使用以提供一个接口,这个接口可用来以一种子系统独立的方式创建子系统。抽象工厂也可以代替外观模式隐藏哪些与平台相关的类
2)中介者模式:
外观模式:是抽象了一组已有类的功能
中介者模式:是抽象了同事之间的任意通信
3)单例模式:Facade对象通常属于单例模式
6、享元模式
(1)功能
运用共享技术有效的支持大量细粒度的对象
(2)适用条件
1)应用程序内使用大量的对象,而这些大量的对象造成了很大的存储开销
2)对象存在外部状态,要使用相对较少的共享对象取代大量的对象
(3)结构
(4)参与者
Flyweight:描述一个接口,通过这个Flyweight接口可以接受和并作用于外部状态
ConcreteFlyweight:继承或者实现Flyweight接口的 。ConcreteFlyweight对象必须是可共享的,它存储的状态必须是内部的,即内部状态应该独立于ConcreteFlyweight对象的场景
内部状态:在享元对象内部,并且不随外部环境改变而改变的共享部分就是享元对象的内部状态。内部状态也就是共享的大量细粒度对象内彼此都相同的部分。
外部状态:随环境改变而改变,不可以共享的状态就是外部状态。外部状态存在于客户端。外部状态就是共享的大量细粒度对象内部彼此差异不相同的部分。将这些(外部状态)从共享对象内部移动到外部,然后在方法调用的时候在传进来,就可以实现通过共享大幅度的减少单个实例的数目。
UnsharedConcreteFlyweight:并非所有的Flyweight子类都需要共享,Flyweight接口是共享成为可能,但是他不是强制的。
FlyweightFacotry:负责创建和管理Flyweight的对象。确保合理的共享Flyweight。当用户请求一个Flyweight的时候,FlyweightFacotry对象提供一个已经创建或者新创建的Flyweight对象(如果不存在的话)
Client:维持对一个Flyweight对象的引用,并计算或者存储一至多个Flyweight的外部状态
(5)优缺点
1)优点:大大减少了实例数目
2)缺点:使系统变得复杂。为了对象可以共享,需要将一些状态外部化,使得程序的逻辑复杂化
(6)相关模式
1)组合模式:享元模式通常和组合模式结合起来使用,用共享叶节点的有向无还图实现一个逻辑上的层次结构
2)状态模式:享元模式使状态对象的最佳实现方式
3)策略模式::享元模式使策略对象的最佳实现方式
7、代理模式
(1)功能
为其他对象提供一种代理商,以控制主公对象的访问
(2)适用条件
1)远程代理一个不在同一个地址空间的对象
2)虚代理一个创建开销很大的对象
3)保护代理:控制对原始对象的访问
4)智能指引:访问对象的时候执行一些附加操作
(3)结构
(4)参与者
Subject: 表示代理类Proxy和被代理类RealSubject公共的接口
Proxy:代理类,引用了被代理类的一个对象。实现了Subject接口
RealSubject: 被代理类,实现了Subject接口
(5)优缺点
(6)相关模式
1)适配器模式:适配器为它所适配的对象提供了不同的接口,而代理模式提供与代理对象相同的接口
2)装饰模式:装饰模式是动态为对象增加功能,而代理模式则是控制对象的访问
三、结构型模式总结
1、结构型模式的对比
结构型模式 |
特性 |
参与者 |
适用场景 |
关联模式 |
适配器模式 |
1、用途:解决两个已有接口的不匹配不兼容问题,不需要对两个独立接口进行重新设计就能够使它们协同工作.(通过适配器协调两个现有类的关系实现代码复用) 2、通常用于系统设计后阶段 3、目的:复用现有类的功能,所以新类需要引用所想要复用的对象。 |
一个现有类 一个适配器类(引用现有类) 一个目标类(使用适配器的类) 适配器内聚合现有类,适配器继承于目标类。 两个组合对象,没有继承关系,相互独立 (相互独立的对象进行组合) |
1)想要复用现有的一个类,但是它的接口又不符合要求时 2)想要创建一个可以复用的类,该类可以与其他不相关的类或者不可预见的类协同工作(即可以与不兼容接口进行协同) |
1、桥接模式: 共同点:都给另一对象提供了一定程度上的间接性,因而有利于系统的灵活性。都涉及到从自身以外的一个接口向这个对象转发请求。 不同点:各自的用途、目标不同 2、装饰模式: 3、代理模式 |
桥接模式 |
1、用途:对抽象部分和实现部分进行桥接。 2、一个抽象部分有多个实现部分,抽象部分和实现部分两者都是独立演化的。 3、目的:实现抽象部分与实现部分的解耦,分离,单独演化,降低依赖性。特别是一个抽象有多个实现的时候。 |
一个实现类的层次结构 一个抽象类的层次结构(聚合抽象类接口) 在抽象类内聚合实现类抽象接口即桥接 两个组合对象,没有继承关系,相互独立 (相互独立的对象进行组合) |
1)不希望抽象部分与实现部分过度耦合 2)实现部分的修改对客户不产生影响,即客户的代码不用重新编译 3)向客户完全隐藏实现部分 4)为避免使用继承造成增加大量的类,且不能满足开放-封闭原则的情况下使用桥接模式 5)一个抽象有多个实现的时候,需要分离抽象和实现 |
1、抽象工厂模式 桥接模式可以由抽象工厂模式来创建和配置一个特定的桥接模式 2、适配器模式 适配器模式:在系统设计完成后使用 桥接模式:在系统设计的时候就开始使用 |
组合模式 |
1、描述了如何构造一个类层次式结构,这一结构有两种类型的对象(基元对象和组合对象)所对应的类型构成。 2、采用递归的方式组合对象 |
一个树形结构组件抽象类 一个叶子节点类 一个有子节点的类 |
1)想要体现部分与整体的层次结构的时候 2)希望用户忽略组合对象和单个对象的不同,统一的使用组合结构中的所有对象时候 |
1、责任链模式: 责任链模式可以由组合模式实现 2、装饰模式: 组合模式经常和装饰模式一起搭配使用 3、享元模式: 4、迭代模式: 5、访问者模式: |
装饰模式 |
1、描述了如何动态的为对象添加职责。 2、采用递归方式组合对象,从而允许添加任意多的对象职责 目的:动态为对象添加功能职责 修饰抽象类内部 |
一个装饰类层次结构 一个被装饰的类 装饰抽象类内引用被装饰的类,装饰类继承于被装饰类 两个组合对象,存在继承关系 (父子对象进行组合) |
1)在不影响其他对象的情况下,以动态,透明的方式给单个对象添加职责 2)处理那些可以撤销的职责 3)需要区分核心职责和装饰功能的时候 |
1、适配器模式 2、组合模式 组合模式经常和装饰模式一起搭配使用 3、策略模式: 策略模式用于改变对象的内核,装饰模式用于改变对象的表示 |
外观模式 |
1、描述了如何用单个对象来描述整个子系统。 | 一组子系统接口 一个外观类,抽象接口 两个组合对象,没有继承关系,相互独立 (两个相互独立的类进行组合) |
1)需要为一个复杂的子系统提供一个简单接口时 2)客户端与抽象的具体实现存在很大的依赖的的时候,引入Facade实现客户端与子系统解耦、分离,提供子系统的独立性和可移植性。 3)当需要构建一个层次结构的子系统,子系统之间彼此分离降低依赖,使用Facade定义子系统中每层的入口点。 |
1、抽象工厂 2、备忘录模式: 3、单例模式:单例模式实现单个外观类对象 |
享元模式 |
1、如何生成很多较小的对象 2、为共享对象定义了一个结构 3、对象共享机制主要强调对象的空间效率,使用对象共享而不是进行对象复制,节省大量的空间资源 4、仅当这些对象没有定义与上下文相关的状态时,才可以被共享。 |
一个共享类的层次结构 一个创建共享类工厂类 |
1)应用程序内使用大量的对象,而这些大量的对象造成了很大的存储开销 2)对象存在外部状态,要使用相对较少的共享对象取代大量的对象 |
1、组合模式 结合使用 2、策略模式 最好使用享元模式实现 3、状态模式 最好使用享元模式实现 |
代理模式 |
1、使用Proxy对象作为其他对象的一个方便的替代或者占位符。 2、起到对被代理对象访问的控制。 3、不改变接口的条件下,为另一个对象定义了一个代理 目的:一个代理对象代理另外一个对象,这个两个对象具有相同的特性,即这两个对象属于同一类型(对外具有统一的接口),所以代理对象内引用它所实际代理的对象。 |
一个现有类,被代理的类 一个代理类(保存一个被代理类的引用) 一个代理类和被代理类的公共接口类 两个组合对象,不存在继承关系,但是属于同一个类型。 (兄弟类对象的组合) |
1)远程代理一个不在同一个地址空间的对象 2)虚代理一个创建开销很大的对象 3)保护代理:控制对原始对象的访问 4)智能指引:访问对象的时候执行一些附加操作 |
1、适配器模式 2、装饰模式 |
2、结构型模式之间的转换
以上是关于设计模式之结构型模式的主要内容,如果未能解决你的问题,请参考以下文章