设计模式之结构型

来源:互联网 发布:通联数据app 编辑:程序博客网 时间:2024/05/21 14:02
  这些设计模式关注类和对象的组合。继承的概念被用来组合接口和定义组合对象获得新功能的方式。

1.适配器模式
  作为两个不兼容的接口之间的桥梁。
  此模式设计单一的类,该类负责加入独立的或不兼容的接口功能,例如读卡器是内存卡和笔记本之间的适配器。
  意图:将一个类的接口转换成客户希望的另一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
  主要解决:将一些“现存的现象”放到新的系统中,而新环境要求的接口是现对象不能满足的。
  何时使用:1.系统需要使用现有的类,而此类的接口不符合系统的需要。2.想要建立一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作,这些源类不一定有一致的接口。3、通过接口转换,将一个类插入另一个类系中。(比如老虎和飞禽,现在多了一个飞虎,在不增加实体的需求下,增加一个适配器,在里面包容一个虎对象,实现飞的接口。)
  如何解决:继承或依赖(推荐)
  关键代码:适配器继承或依赖已有的对象,实现想要的目标接口。
  优点:1.可以让任何两个没有关联的类仪器运行。2.提高了类的复用。3.增加了类的透明度。4.灵活性好
  缺点:1、过多地使用适配器,会让系统非常零乱,不易整体进行把握。比如,明明看到调用的是 A 接口,其实内部被适配成了 B 接口的实现,一个系统如果太多出现这种情况,无异于一场灾难。因此如果不是很有必要,可以不使用适配器,而是直接对系统进行重构。2.由于 JAVA 至多继承一个类,所以至多只能适配一个适配者类,而且目标类必须是抽象类。
  使用场景:有动机地修改一个正常运行的系统的接口,这时应该考虑使用适配器模式。
  注意事项:适配器不是在详细设计时添加的,而是解决正在服役的项目的问题。
 
2.桥接模式
  通过提供抽象化与实现化之间的桥接结构,把抽象化与实现化解耦,使得二者可以独立变化。
  此模式设计一个作为桥接的接口,使得实体类的功能独立于接口实现类。
意图:将抽象部分与实现部分分离,使它们都可以独立的变化。
主要解决:在多种可能会变化的情况下,用继承会造成类爆炸问题,扩展起来不灵活。
何时使用:实现系统可能有多个角度分类,每一种角度都可能变化。
如何解决:把这种多角度分类分离出来,让它们独立变化,减少它们之间的耦合。(即,原本通过继承来解决的多角度问题,此时使用变化分离的方法,将变化与不变的部分分开,变化的部分Impl一个接口,而不变的部分则只需要通过上面的接口来调用急了。)
关键代码:抽象类依赖实现类
优点:1.抽象与实现的分离。2.优秀的扩展能力。 3.实现细节对客户透明
缺点:桥接模式的引用会增加系统的理解与设计难度,由于聚合关联关系建立在抽象层,要求开发者针对抽象进行设计和编程。
使用场景: 1.如果一个系统需要在构件的抽象化角色和具体化角色之间增加更多的灵活性,避免在两个层次之间建立静态的继承联系,通过桥接模式可以使它们在抽象层建立一个关联关系。2、对于那些不希望使用继承或因为多层次继承导致系统类的个数急剧增加的系统,桥接模式尤为适用。3、一个类存在两个独立变化的维度,且这两个维度都需要进行扩展。
注意事项:对于两个独立变化的维度,使用桥接模式再适合不过了。(如果用实现,那么子类的个数就是2^n,类的数量呈指数级增长,而如果分开使用桥接,那么新增的类只有2n个,呈直线增长。)

3.过滤器模式
  过滤器模式(Filter Pattern)或标准模式(Criteria Pattern)是一种设计模式,它允许开发人员使用不同的标准来过滤一组对象,通过逻辑运算以解耦的方式把它们连接起来。即结合多个标准来获得单一标准。

4.组合模式
  组合模式(Composite Pattern),又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象。依据树形结构来组合对象,用来表示部分以及整体层次。创建了对象组的树形结构。
  此模式创建了一个包含自己对象组的类,该类提供了修改相同对象组的方式。(即每个对象都会有自己的下属对象——可能是null)
  (即,对象之间的差异是通过此树形结构构成的,例如一个公司的员工职位等级)

意图:将对象组合成树形结构以表示“部分--整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。(因为差异是通过包含对象组的形式实现的,即对于每一个对象的对象组中的成员来说,它们是部分,而此对象可以看成整体)
主要解决:在树形结构的问题中,模糊了简单元素和复杂元素的概念(都变成一种元素了),客户程序可以像处理简单元素一样来处理复杂元素,从而使客户程序与复杂元素的内部结构解耦。
何时使用:1.您想表示对象的部分-整体层次结构(树形结构);2.希望用户忽略组合对象鱼单个对象的不同,用户将统一地使用组合结构中的所有对象。
如何解决:树枝和叶子实现统一接口,树枝内部组合该接口。
关键代码:树枝内部组合该接口,而且含有内部属性list,里面放component
优点:1.高层模块调用简单。2.节点自由增加
缺点:在使用组合模式时,其叶子和树枝的声明都是实现类,而不是接口,违反了依赖倒置原则(即应该依赖于接口,而不是具体的类)
使用场景:部分、整体场景,如树形菜单,文件、文件夹的管理。
注意事项:定义时未具体类。

5.装饰器模式
  装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。它是作为现有类的一个包装。
  此模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。

意图:动态地给一个对象添加一些额外的职责。就增加功能来说,装饰器模式比生成子类更为灵活。
主要解决:一般的,为了扩展一个子类经常使用继承方式实现,由于继承为类引入静态特征,并且随着扩展功能的增多,子类会很膨胀。
何时使用:在不想增加很多子类的情况下扩展类。
如何解决:将具体功能职责划分,同时继承装饰者模式
关键代码:1.Component类充当抽象角色,不应该具体实现;2.修饰类引用和继承Component类,具体扩展类重写父类方法。
优点:装饰类和被装饰类可以独立发展,不会相互耦合,装饰器模式是继承的一个替代模式,装饰器模式可以动态扩展一个实现类的功能。
缺点:多层修饰比较复杂。
使用场景:1.扩展一个类的功能。2.动态增加功能,动态撤销。
注意事项:可代替继承。

6.外观模式
  外观模式(Facade Pattern)隐藏系统的复杂性,并向客户端提供了一个客户端可以访问系统的接口。
  此模式设计单一的类,该类提供了客户端请求的简化方法和对现有系统类方法的委托调用。(即它包含了子系统可以提供的所有功能接口)

意图:为子系统中的一组接口提供一个一致的接口,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
主要解决:降低访问复杂系统的内部子系统时的复杂度,简化客户端与之的接口。
何时使用:1、客户端不需要知道系统内部的复杂联系,整个系统只需提供一个"接待员"即可。2、定义系统的入口。
如何解决:客户端不与系统耦合,外观类与系统耦合。
关键代码:在客户端和复杂系统之间再加一层,这一层将调用顺序、依赖关系等处理好。
应用实例:1、去医院看病,可能要去挂号、门诊、划价、取药,让患者或患者家属觉得很复杂,如果有提供接待人员,只让接待人员来处理,就很方便。2、JAVA 的三层开发模式。
优点:1、减少系统相互依赖。2、提高灵活性。3、提高了安全性。
缺点:不符合开闭原则,如果要改东西很麻烦,继承重写都不合适。
使用场景:1、为复杂的模块或子系统提供外界访问的模块。2、子系统相对独立。3、预防低水平人员带来的风险。
注意事项:在层次化结构中,可以使用外观模式定义系统中每一层的入口。

7.享元模式
  享元模式(Flyweight Patten)主要用于减少创建对象的数量,以减少内存占用和提高性能。
  此模式尝试重用现有的同类对象,如果未找到匹配的对象,再创建新对象。

意图:运用共享技术有效地支持大量细粒度的对象。
主要解决:在有大量对象时,有可能造成内存溢出,我们将其中共同的部分抽象出来,如果有相同的业务请求,直接返回在内存中已有的对象,避免重复创建。
何时使用:1.内存中存在大量对象。2.这些对象消耗大量内存。3.这些对象的状态大部分可以外部化。4.这些对象可以按照内蕴状态分为很多组,当把外蕴对象从对象中剔除出来时,每一组对象都可以用一个对象来代替。5.系统不依赖于这些对象身份,这些对象时不可分辨的。
如何解决:用唯一标识码判断,如果在内存中有,则返回这个唯一标识码所标识的对象。
关键代码:用HashMap存储这些对象(键为标识码,值为一个典型的对象)
优点:大大减少对象的创建,降低系统的内存,使效率提高
缺点:提高了系统的复杂度,需要分离出外部状态和内部状态,而且外部状态具有固有化的性质,不应该随着内部状态的变化而变化,否则会造成系统的混乱。
使用场景:1.系统有大量相似对象。2.需要缓冲池的场景。
注意事项:1.注意划分外部状态和内部状态,否则可能会引起线程安全问题。2.这些类必须有一个工厂对象加以控制。(这个所谓的外部状态应该是同类对象不同的地方,也就是区别)

8.代理模式
  在代理模式(Proxy Pattern)中,一个对象代表另一个类的功能。
  此模式中,创建具有现有对象的对象,以便向外界提供功能接口。


意图:为其他对象提供一种代理以控制对这个对象的访问。
主要解决:在直接访问对象时带来的问题,比如说:要访问的对象在远程的机器上。在面向对象系统中,有些对象由于某些原因(比如对象创建开销很大,或者某些操作需要安全控制,或者需要进程外的访问),直接访问会给使用者或者系统结构带来很多麻烦,我们可以在访问此对象时加上一个对此对象的访问层。
何时使用:想在访问一个类时做一些控制。
如何解决:增加中间层。
关键代码:实现与被代理类组合。
优点:1、职责清晰。2、高扩展性。3、智能化。
缺点:1、由于在客户端和真实主题之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢。2、实现代理模式需要额外的工作,有些代理模式的实现非常复杂。
使用场景:按职责来划分,通常有以下使用场景:1、远程代理。2、虚拟代理。3、Copy-on-Write 代理。4、保护(Protect or Access)代理。5、Cache代理。6、防火墙(Firewall)代理。7、同步化(Synchronization)代理。8、智能引用(Smart Reference)代理。
注意事项:1、和适配器模式的区别:适配器模式主要改变所考虑对象的接口,而代理模式不能改变所代理类的接口。2、和装饰器模式的区别:装饰器模式为了增强功能,而代理模式是为了加以控制。
原创粉丝点击