结构型设计模式对比 设计模式(十六)

结构型设计模式

结构型模式关注于整体最终的结构,通过继承和组合,构建出更加复杂的结构

进而提供更加强大的逻辑功能

七种结构型模式

  • 适配器模式(Adapter Pattern)
  • 组合模式(Composite Pattern)
  • 装饰器模式(Decorator Pattern)
  • 代理模式(Proxy Pattern)
  • 桥接模式(Bridge Pattern)
  • 外观模式(Facade Pattern)
  • 享元模式(Flyweight Pattern)

所有的结构型设计模式在逻辑上都各自不同程度的隐含了“间接”“代理”“委托”的含义 ,有的明显,有的含蓄

强表现

适配器、装饰器、代理、组合、桥接模式,这几种模式比较强烈的表现了“间接”“代理”“委托”的含义 

从图中可以清楚地看得出来,他们都有“代理”的含义


适配器模式,通过继承或者组合方式,“代理”了,被适配角色Adaptee

装饰器模式,通过组合的方式,"是你还有你",内部拥有Component,代理了被装饰的具体构建 ConcreteComponent
代理模式,通过组合的方式,内部拥有RealSubject,代理了真实主题角色
组合模式,通过组合的方式,内部包含叶子节点或者树枝节点,内部“代理”了 子对象
桥接模式,通过组合的方式,内部拥有Implementor,指向实现者

如果装饰器模式只有一个被装饰的类ConcreteComponent,也只有一个装饰器角色ConcreteDecorator

省略掉Decorator ,他跟代理模式的结构可以说是一样的

省略掉装饰器模式结构图中的ConcreteDecorator角色,组合模式和装饰器模式的结构就完全一样了

如果只有一种类型的ConcreteImplementor,桥接模式又与对象适配器模式相同

虽然说他们都有“代理”的含义,但是他们又有很大差别

适配器模式下,“代理”的对象是功能相近的替代方案,比如,插座适配器可以进行插头转换
使得原本不兼容,不能够一起工作的那些类能够一起工作

代理模式下,“代理”的真实主题的对象RealSubject,从而对真实对象进行隐藏,封装

透明的对外界提供服务,控制外界对这个对象的访问

装饰器模式下,“代理”的是抽象的Component构建,能够代理所有的ConcreteComponent类型
装饰器和被装饰的构建都是Component,重点在于功能的扩展,添加额外的职责
组合模式下,“代理”的是抽象构建Component,代理的是子对象,用于描述“整体-部分”的概念
桥接模式,“代理”的是实现角色Implementor,代理的是具体的实现,用于将抽象与实现进行分离
分离后通过桥接模式进行连接

他们虽然都是“代理”,但是他们的侧重点不同,被代理的事物的性质不同

适配器模式在代理的过程中,重点在于适配,不会增加额外的功能

代理模式侧重于控制,当然也通常用于增加功能

如果代理模式,代理的不是真实主题对象RealSubject,而是抽象构建Subject,显然,就演化成了装饰器模式

因为代理模式不光能够控制外界对真实对象的访问,他也能够提供额外的服务

装饰器模式则是重点在于功能的扩展,增肌额外的职责

而组合模式,重点在于形成“整体--部分”的结构,并且对外界客户端程序,提供一致的访问形式

弱表现

享元模式和外观模式也是一定程度的代理

享元模式,通过内部状态与外部状态的分离,通过享元池中的享元对象,代理了所有的具有内外状态完整的对象

对客户端来说就是有如此多的对象, 只不过内存中却仅有少量的对象

外观模式在结构上完全看不出来“代理”的含义,但是他在业务逻辑上充当的也恰恰是“接口人”“协调者”“控制台”的角色

所以也可以认为是“代理”了内部的子系统

代理模式与适配器模式

代理模式和适配器模式都需要借助于内部的“被代理”对象,或者“被适配者”对象进行工作

也就是说他们都将自己的工作委托出去

但是代理模式中,代理者与被代理者他们拥有相同的接口,也就是拥有相同的对外呈现,重点在于对真实对象的隐藏,客户端请求的透传,并且可以额外的增加一些控制,管理

适配器模式中,目标对象和被适配者在接口上没有必然联系,比如目标是港版插座面板,被适配者是大陆插座面板,他们的共同点是提供电力,但是接口却完全不同

适配器的重点在于不能一起工作的类能够一起工作

代理模式与装饰器模式

代理模式提供与被代理的真实对象相同的访问接口,对真实对象进行一定的控制,也可以增加额外的服务,职责

装饰器模式也是代理了内部真实的对象,并且拥有相同的访问接口

但是代理模式重点在于增加对真实对象的控制,隐藏真实对象,一般会在代理类内部创建一个真实的对象

也就是说这种代理关系在编译时期已经静态确定了

代理类接受处理来自客户端的请求,在内部转发到真实主题对象上

比如

//代理模式
public class Proxy implements Subject{
private Subject realSubject;
public Proxy(){
//关系在编译时确定
realSubject = new RealSubject();
}
public void doSth(){
….
realSubject.doSth();
….
}
}

装饰器模式在于功能的动态增加,所以对象一般作为参数进行传递,比如:

InputStream inputStream = new BufferedInputStream(new FileInputStream("........"));

这是一种在运行期间动态增加功能方式

适配器与外观模式

适配器模式将一种接口转换为另外一种接口,使得原本不能一起工作的类可以协作

外观模式是将子系统的的多个接口的访问转换为另一种接口,使得原本复杂难用,耦合程度高的多个类有一个一致简单的接口

他们都变成了另外一种形式的接口

所有的请求也都是委托他人进行处理,适配器模式委托给被适配角色,外观模式委托给子系统

适配器模式是为了能够一起工作,他们原本是并不兼容的

外观模式是为了能够更好地更简单的工作,他们原本是可以一起工作的

桥接模式与适配器模式

适配器模式的主要目的是让因为接口不兼容而不能互相工作的类能够一起工作

换句话说就是他们本身不同,我用“纽带” Adapter将他们连接起来

桥接模式则是将原本或许紧密结合在一起的抽象与实现,进行分离

使她们能够各自独立的发展,是把连接在一起的两个事物,拆分开来

然后用“纽带”“桥梁”(也就是对象的引用)将他们连接起来

适配器模式就好比张三和王五不认识,李四介绍他们认识

桥梁模式好比张三和王五成天黏在一起活干得不好太乱套,李四说以后我作为接口人,你俩各干各的吧

虽然看起来都是两个人干活,中间一个联系人,但是含义却是完全不同

桥接模式与装饰器模式

装饰器模式中,使用组合而不是继承来对类的功能进行扩展

避免了类的个数的爆炸增长,与桥梁模式的结果不约而同

他们都解决了类爆炸增长的问题,都避免了过多的没必要的子类

装饰器模式侧重于功能的动态增加,将额外的功能提取到子类中

通过不同的排列组合,形成一个递归的调用方式,以动态的增加各部分的功能

桥梁模式是将原本系统中的实现细节抽取出来,比如原来抽象概念与实例化全部都是一个类层次结构中

把所有的实现细节,比如示例中的平台相关实现,抽取出来,进行分离,达到抽象与实现分离的目的

所以虽然他们都可以解决子类爆炸式增长、不易扩展的问题

但是他们的出发点完全不同

一个关注于功能的动态扩展组合

一个关注于抽象与实现的分离,获得更多的灵活性

总结

所有的结构型模式的都离不开“分离,解耦”的概念

而“分离,解耦”之后,又通过某种形式建立联系,比如“组合”

抽象与实现进行分离,分离就意味着独立,独立就意味着可以单独发展,桥接模式

对于分离的事物通过委托的形式托付工作,就可以在中间提供更多的服务,代理模式

而分离的两个事物也可以通过一定形式的结合、转换进而一起协同工作,适配器模式

将一个对象的多个功能点进行分离,从而能够动态的组合以形成更强大的功能,装饰器模式

将事物自身内部核心状态与外部状态进行分离,进而减少核心状态的存储运行消耗,享元模式

将客户端与子系统的耦合交互进行分离,抽象出来一个新的接入点,外观Facade,降低耦合,外观模式

分离开的多种事物,如果他们有“整体--部分”的关系,可以将它们组合在一起,形成更复杂的整体结构,组合模式

(ps:上面的分离指分开的,不耦合在一起,不是特指原本是一个整体,被分成两部分)

以上各个部分的差异对比点主要根据设计模式的最初意图、动机,设计模式本就是设计原则的实现化角色

对于任何的结构,你都可以按照你自己的想法去使用、拓展,当然,前提是更合适或者更优秀

否则您那是瞎用

比如代理模式与装饰器模式本就很类似,如果你将代理模式的真实对象也是作为参数进行传递

也是用来动态的增加职责,那么就成了装饰器模式,所以再回头,你说你的是代理模式还是装饰器模式?

这么看这个名字代理还是装饰器又有什么大的区别的呢?都只是用来叙述而已

但是如果你这么做还非要说是代理模式,有一个很大的问题就是和同事、领导沟通起来就特别费劲了,说不定还会吵起来...

所以,除非你有更好更合适的选择,或者改变

否则,一定要尽量按照模式原本的意图和动机去使用某种模式

原文地址:结构型设计模式对比 设计模式(十六)

原文地址:https://www.cnblogs.com/noteless/p/10080950.html

时间: 2024-12-15 06:53:13

结构型设计模式对比 设计模式(十六)的相关文章

Java 设计模式系列(十六)观察者模式(Observer)

Java 设计模式系列(十六)观察者模式(Observer) 观察者模式是对象的行为模式,又叫发布-订阅(Publish/Subscribe)模式.模型-视图(Model/View)模式.源-监听器(Source/Listener)模式或从属者(Dependents)模式. 观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象.这个主题对象在状态上发生变化时,会通知所有观察者对象,使它们能够自动更新自己. 一.观察者模式的结构 Subject:目标对象,通常具有如下功能:

设计模式(34)-----结构型模式-----桥接设计模式

桥接(Bridge)是用于把抽象化与实现化解耦,使得二者可以独立变化.这种类型的设计模式属于结构型模式,它通过提供抽象化和实现化之间的桥接结构,来实现二者的解耦. 这种模式涉及到一个作为桥接的接口,使得实体类的功能独立于接口实现类.这两种类型的类可被结构化改变而互不影响. 我们通过下面的实例来演示桥接模式(Bridge Pattern)的用法.其中,可以使用相同的抽象类方法但是不同的桥接实现类,来画出不同颜色的圆. 介绍 意图:将抽象部分与实现部分分离,使它们都可以独立的变化. 主要解决:在有多

设计模式学习(十六) 模板方法模式

场景: -- 客户到银行办理业务 1:取号排队 2:办理具体现金/转账/企业/个人/理财业务 3: 给银行工作人员评分 模板方法介绍; -- 模板方法模式是编程中经常用到的模式,它定义了一个操作中的算法骨架,将某些步骤延迟到子类中实现.这样,新的子类可以在不改变一个算法结构的前提下重新定义该算法的某些特定步骤 核心: -- 处理某个流程的代码已经都具备,但是其中某个节点的代码暂时不能确定.因此,我们采用模板方法模式.将这个节点的代码实现转移给子类完成.即:处理步骤父类中定义好,具体实现延迟到子类

Java设计模式菜鸟系列(十六)原型模式建模与实现

转载请注明出处:http://blog.csdn.net/lhy_ycu/article/details/39997337 原型模式(Prototype):该模式的思想就是将一个对象作为原型,对其进行复制.克隆,产生一个和原对象类似的新对象.而这里的复制有两种:浅复制.深复制. 浅复制:将一个对象复制后,基本数据类型的变量都会重新创建,而引用类型,指向的还是原对象所指向的. 深复制:将一个对象复制后,不论是基本数据类型还有引用类型,都是重新创建的.简单来说,就是深复制进行了完全彻底的复制,而浅复

javascript设计模式学习之十六——状态模式

状态模式的关键是区分事务内部和外部的状态,事务内部状态改变往往会带来事务的行为改变. 状态模式中有意思的一点是,一般我们谈到封装,都是优先封装对象的行为,而非对象的状态.但在状态模式中刚好相反,状态模式的关键是把事务的每种状态都封装为单独的类,跟此种状态有关的行为都封装在这个类的内部.与此同时,我们还可以把状态的切换规则实现分布在状态类中,这样就有效消除了原本存在的大量条件分支语句.

设计模式C++实现十六:迭代器模式

迭代器模式(Iterator):提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露该对象的内部表示. 使用场景:当我们需要访问一个聚集对象时,而且不管这些对象是什么都需要遍历的时候,我们可以考虑使用迭代器模式.如果我们需要对聚集有多种方式遍历时,也可以考虑使用迭代器模式.迭代器一般需要提供开始,下一个,是否结束,当前项的内容等方法. #ifndef ITERATOR_H #define ITERATOR_H #include<iostream> #include<string>

设计模式(35)-----设计模式阶段性总结(一句话概括一个模式)

目录: 设计模式(1)------初始设计模式(回调函数) 设计模式要从语义上出发,而不要从语法上出发,其实设计模式归根结底就是多态的有计划的组合. 设计模式(2)------行为型模式------观察者设计模式 想想气象站,根据天气的变化动态的通知观众实时天气.当一个对象的状态改变时,通知另一个对象作出相应的改变,而中间的观察和通知者就是主要的观察者设计模式.出版者+订阅者=观察者模式 设计模式(3)------行为型模式------观察者设计模式(jdk自带) 设计模式(4)------结构

设计模式(十):Decorator装饰者模式 -- 结构型模式

1. 概述 若你从事过面向对象开发,实现给一个类或对象增加行为,使用继承机制,这是所有面向对象语言的一个基本特性.如果已经存在的一个类缺少某些方法,或者须要给方法添加更多的功能(魅力),你也许会仅仅继承这个类来产生一个新类—这建立在额外的代码上. 通过继承一个现有类可以使得子类在拥有自身方法的同时还拥有父类的方法.但是这种方法是静态的,用户不能控制增加行为的方式和时机.如果  你希望改变一个已经初始化的对象的行为,你怎么办?或者,你希望继承许多类的行为,改怎么办?前一个,只能在于运行时完成,后者

设计模式(十二): Flyweight享元模式 -- 结构型模式

说明: 相对于其它模式,Flyweight模式在PHP实现似乎没有太大的意义,因为PHP的生命周期就在一个请求,请求执行完了,php占用的资源都被释放.我们只是为了学习而简单做了介绍. 1. 概述 面向对象技术可以很好地解决系统一些灵活性或可扩展性或抽象性的问题,但在很多情况下需要在系统中增加类和对象的个数.当对象数量太多时,将导致运行代价过高,带来性能下降等问题.比如:例子1:图形应用中的图元等对象.字处理应用中的字符对象等. 2.解决方案: 享元模式(Flyweight):对象结构型模式运用