设计模式之结构型模式

适配器模式

适配器模式可以将一个类的接口和另一个类的接口匹配起来,无须修改原来的适配者接口和抽象目标类结构。根据适配器类与适配者类的关系不同,适配器模式可以分为对象适配器和类适配器两种,在对象适配器模式中,适配器与适配者之间是关联关系;在类适配器模式中,适配器和适配者之间是机场关系。在实际开发中,对象适配器使用频率更高,如下图所示
适配器模式

总结

优点
  1. 将目标类和适配者类解耦,通过引入一个适配器类来重用现有的适配者类,无须修改原有结构。
  2. 增加类的透明性和复用性,将具体的业务实现过程封装在适配者类中,对于客户端类而言是透明的且提高了适配者的复用性,同一个适配者类可以在过个不同的系统中复用。
  3. 灵活性和扩展性都非常好,通过使用配置文件,可以很方便地更换适配器,也可以在不修改原有代码基础上增加新的适配器类,完全符合“开闭原则”

桥接模式–处理多维度变化

假如我们需要大中小3种型号的画笔,能够绘制12种不同的颜色,如果使用蜡笔,需要准备3×12 = 36支,但如果使用毛笔的话,只需要提供3种型号的毛笔,外加12个颜料盒即可,涉及到的对象个数仅为 3 + 12 = 15,远小于36,却能实现与36支蜡笔同样的功能。
桥接模式是一种很实用的结构型设计模式,如果软件系统中某个类存在两个独立变化的维度,通过该模式可以将两个维度分离出来,使两者可以独立扩展,让系统更加符合“单一职责原则”。如下图所示
桥接模式
在桥接模式结构图中包含如下几个角色:
●Abstraction(抽象类):用于定义抽象类的接口,它一般是抽象类而不是接口,其中定义了一个Implementor(实现类接口)类型的对象并可以维护该对象,它与Implementor之间具有关联关系,它既可以包含抽象业务方法,也可以包含具体业务方法。
●RefinedAbstraction(扩充抽象类):扩充由Abstraction定义的接口,通常情况下它不再是抽象类而是具体类,它实现了在Abstraction中声明的抽象业务方法,在RefinedAbstraction中可以调用在Implementor中定义的业务方法。
●Implementor(实现类接口):定义实现类的接口,这个接口不一定要与Abstraction的接口完全一致,事实上这两个接口可以完全不同,一般而言,Implementor接口仅提供基本操作,而Abstraction定义的接口可能会做更多更复杂的操作。Implementor接口对这些基本操作进行了声明,而具体实现交给其子类。通过关联关系,在Abstraction中不仅拥有自己的方法,还可以调用到Implementor中定义的方法,使用关联关系来替代继承关系。
●ConcreteImplementor(具体实现类):具体实现Implementor接口,在不同的ConcreteImplementor中提供基本操作的不同实现,在程序运行时,ConcreteImplementor对象将替换其父类对象,提供给抽象类具体的业务操作方法。
桥接模式是一个非常有用的模式,在桥接模式中体现了很多面向对象设计原则的思想,包括“单一职责原则”、“开闭原则”、“合成复用原则”、“里氏代换原则”、“依赖倒转原则”等。熟悉桥接模式有助于我们深入理解这些设计原则,也有助于我们形成正确的设计思想和培养良好的设计风格。
在使用桥接模式时,我们首先应该识别出一个类所具有的两个独立变化的维度,将它们设计为两个独立的继承等级结构,为两个维度都提供抽象层,并建立抽象耦合。通常情况下,我们将具有两个独立变化维度的类的一些普通业务方法和与之关系最密切的维度设计为“抽象类”层次结构(抽象部分),而将另一个维度设计为“实现类”层次结构(实现部分)。例如:对于毛笔而言,由于型号是其固有的维度,因此可以设计一个抽象的毛笔类,在该类中声明并部分实现毛笔的业务方法,而将各种型号的毛笔作为其子类;颜色是毛笔的另一个维度,由于它与毛笔之间存在一种“设置”的关系,因此我们可以提供一个抽象的颜色接口,而将具体的颜色作为实现该接口的子类。在此,型号可认为是毛笔的抽象部分,而颜色是毛笔的实现部分,结构示意图如图所示:
这里写图片描述

总结

优点
  1. 分离抽象接口及其实现部分
  2. 在很多情况下,桥接模式可以取代多层集成方案。
  3. 桥接模式提高了系统的可扩展性,在两个变化维度中任意扩展一个维度,都不需要修改原有系统。
缺点
  1. 桥接模式会增加系统的理解和设计难度
  2. 桥接模式要求正确识别出两个独立变化的维度,因此其使用范围具有一定的局限性。

组合模式–树形结构处理

组合模式:组合多个对象形成树形结构以表示具有“整体-部分”关系的层次结构。组合模式对单个对象和组合对象的使用具有一致性,组合模式又可以成为“整体部分”模式。
在组合模式中引入了抽象构件类Component,它是所有容器类和叶子类的公共父类,客户端针对Component进行编程,如图:
组合模式
组合模式的关键是定义了一个抽象构件类,它既可以代表叶子,又可以代表容器,而客户端针对该抽象构件类进行编程,无须知道它到底表示的是叶子还是容器,可以对其进行统一处理。同时容器对象与抽象构件类之间还建立一个聚合关联关系,在容器对象中既可以包含叶子,也可以包含容器,以此实现递归组合,形成一个树形结构。

总结

优点
  1. 组合模式可以清楚地定义分层次的复杂对象,表示对象的全部或者部分层次
  2. 客户端可以一致地使用一个组合结构或其中单个对象,不必关心处理的是单个对象还是整个组合结构
  3. 在组合模式中增加新的容器构件和叶子构件都很方便,无须对现有类库进行任何修改
  4. 组合模式为树形结构的面向对象实现提供了一种灵活的解决方案,通过叶子对象和容器对象的递归组合,可以形成复杂的树形结构,但对树形结构的控制却非常简单
缺点

在增加新构件时很难对容器中的构建类型进行限制。有时候我们希望一个容器中只能有某些特定类型的对象,例如在某个文件夹中只能包含文本文件,使用组合模式时,不能依赖类型系统来施加这些约束,因为它们都来自于相同的抽象层。

装饰模式–扩展系统功能

装饰模式可以在不改变一个对象本身功能的基础上给对象增加额外的新行为。装饰模式是一种用于替代继承的技术,通过一种无须定义子类的方式来给对象动态增加职责,使用对象之间的关联关系取代类之间的继承关系。如图:
装饰模式

总结

装饰模式降低了系统的耦合度,可以动态增加或删除对象的职责,并使得需要装饰的具体构件类和具体装饰类可以独立变化,以便增加新的具体构件类和具体装饰类。

优点
  1. 对于扩展一个对象的功能,装饰模式比继承更加灵活,不会导致类的个数急剧增加。
  2. 可以通过一种动态的方式来扩展一个对象的功能
  3. 可以对一个对象进行多次装饰,通过使用不同的具体装饰类以及这些装饰类的排列组合,可以创造出很多不同行为的组合,得到功能更为强大的对象。
  4. 具体构建类与具体装饰类可以独立变化,用户可以根据需要增加新的具体构件类和具体装饰类,原有类库代码无须改变。
缺点
  1. 使用装饰模式进行系统设计时将产生很多小对象,这些对象的区别在于它们之间相互连接的方式有所不同,而不是它们的类或者属性值有所不同
  2. 装饰模式提供了一种比集成更加灵活机动的解决方案,但是同时也意味着比继承更加易于出错,排错很困难。

外观模式

外观模式是一种使用频率非常高的结构型设计模式,通过引入一个外观角色来简化客户端与子系统之间的交互,为复杂的子系统调用提供一个统一的入口,降低子系统与客户端的耦合度,且客户端调用非常方便。如图:
这里写图片描述

总结

外观模式是一种使用频率非常高的设计模式,通过引入一个外观角色来简化客户端与子系统之间的交互,为复杂的子系统调用提供一个统一的入口,使子系统与客户端的耦合度降低,且客户端调用非常方便。

优点
  1. 对客户端屏蔽了子系统组件,减少了客户端所需处理的对象数目
  2. 实现了子系统与客户端之间的松耦合
  3. 子系统修改对其他子系统没有任何影响
缺点
  1. 不能很好地限制客户端直接使用系统类
  2. 如果设计不当,增加新的子系统可能需要修改外观类源代码。

    享元模式–实现对象复用

    享元模式(Flyweight Pattern):运用共享技术有效地支持大量细粒度对象的复用。系统只使用少量的对象,而这些对象都很相似,状态变化很小,可以实现对象的多次复用。由于享元模式要求能够共享的对象必须是细粒度对象,因此它又称为轻量级模式,它是一种对象结构型模式。如图
    享元模式

    总结

    当系统中存在大量相同或者相似的对象时,享元模式是一种较好的解决方案,它通过共享技术实现相同或相似的细粒度对象的复用,从而节约了内存空间,提高了系统性能。

    优点
  3. 极大减少内存中对象的数量

  4. 外部状态独立
缺点
  1. 系统变得复杂
  2. 为了使对象可以共享,享元模式需要将对象的部分状态外部化

代理模式

代理模式:给某一个对象提供一个代理或占位符,并由代理对象来控制对原对象的访问。代理对象在客户端对象和目标对象之间起到中介作用,它去掉客户不能看到的内容和服务或者增添客户需要的额外的新服务。常见的代理形式包括远程代理、保护代理、虚拟代理、缓冲代理、只能引用代理。如图:
代理模式

总结

代理模式是常用的结构型设计模式之一,他为对象的简介访问提供了一个解决方案,可以对对象的访问进行控制。

优点
  1. 协调调用者和被调用者,一定程度上降低了系统的耦合度
  2. 客户端可以针对抽象主题角色进行编程,增加和更换代理类无须修改源代码。
缺点
  1. 增加代理对象,处理速度变慢
  2. 实现代理模式需要额外的工作
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值