结构型模式包含了七种设计模式:适配器模式、桥接模式、组合模式、代理模式、装饰模式、外观模式和享元模式。
结构模式中涉及了一个问题:类与对象之间的组合关系(此组合非UML图关系中的组合)。
1.适配器模式:将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
1.1 UML图
1.2 模式解析:客户端对一个需要适配的类发出请求,但由于二者接口不统一(比如方法名不同),所以需要适配的类无法执行请求;而适配器与客户端有同一套标准,因此这时加入一个适配器类处理:在适配器内包装一个需要适配的类(在自己的方法名中以需要适配的类能接收的标准向其发送请求),也就是说适配器代替需要适配的类接下了客户端的命令。
为了更好理解,我们可以在Target类下再加几个继承于其本身的类,只是这些类不需要适配,因为它们本身的接口与客户端发送的命令是相匹配的,此时我们会发现,适配器本身的框架和其他几个不需要适配的类本质是相同的。
1.3 模式适用情况:在双方都不太容易修改接口标准的时候使用适配器模式。
2.桥接模式:将抽象部分与它的实现部分分离,使它们都可以独立地变化。
2.1 UML图:
2.2 模式解析:由于这两个类(抽象类与实现类)都是多变的类,若使二者为继承关系,会在任意一个类发生变化时导致许多不必要的类的增加,占用内存,所以要将关系改为聚合关系,从而降低耦合度。
2.3 合成/聚合复用原则:尽量使用合成/聚合,尽量不要使用类的继承。
个人理解:聚合是一种弱关联,A对象可以包含B对象,但B对象并不是A对象的一部分;合成则是一种强关联,A对象与B对象有着严格的部分整体关系。在桥接模式中,抽象类可以包含实现类,但实现类并不是抽象类的一部分(一个篮球队里有一名队员A,但这个队员A脱离了组织也可以自己玩球)。
2.4 模式适用条件:抽象类与实现类之间并没有太强的关联并且二者多变,若使用继承关系将会使体系发展成一个庞然大物的情况下。
3.组合模式:将对象组合成树形结构以表示“部分-整体“的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。
3.1 UML图:
3.2 模式解析:该模式理解起来并不困难:子类的某个部件与父类在结构上具有一致性的时候(树型结构),使用此模式。
3.3 模式适用情况:需求中是体现部分与整体层次的结构时,以及希望用户可以忽略组合对象与单个对象的不同时。
4.代理模式:为其他对象提供一种代理以控制对这个对象的访问。
4.1 MUL图:
4.2 模式解析:这个模式依赖代理类实现真实实体(通过代理类与真实实体类都共用一个接口来实现,因此在任何可用真实实体类的地方都可以使用代理)。
4.3 模式适用情况:远程代理和虚拟代理。
5.享元模式:运用共享技术有效地支持大量细粒度的对象。
5.1 UML图:
5.2 模式解析:享元模式中也用到了工厂,在这一点上和简单工厂模式上较为相似。
享元工厂用来创建并管理Flyweight对象:客户端发出请求时,提供一个已有的实例或是创建一个实例。这句话可以这样理解:工厂内先实例化几个具体享元类,若在之后客户端请求的实例已经存在则直接调用无需新建,节省内存,若没有则再建一个实例。
5.3 模式适用情况:一个应用程序使用了大量的对象,而大量的对象造成了很大的存储开销时考虑使用;或是对象的大多数状态可以外部状态
6.外观模式:为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
6.1 UML图:
6.2 模式解析:客户端内有关要执行的功能细节过多(知道了太多的细节),从而使耦合度过高;而外观模式变成了客户端只要调用一个媒介即可,由媒介来决定要执行什么细节。另外Facade类只是给子系统提供了一个易于使用的接口,并无任何继承关系,因此在子系统的类中没有Facade的任何信息。
6.3 模式适用情况:
1.设计初期,应该将不同的两个曾分离;
2.开发阶段:子系统会因为重构而变得复杂;
3.维护阶段:这个系统很难维护与扩展了。
7.装饰模式:动态地给一个对象添加一些额外的职责,就增加功能而言,装饰模式比生成子类更灵活。
7.1 UML图:
7.2 模式解析:为一个类动态地添加装饰类的方法(功能):通过由具体装饰类包装好需要添加职责的类来实现。
7.3 模式适用情况:系统的新功能需要从已有的类中使用。