结构模式描述如何将类或对象结合在一起,组成一个更大的结构。
分类:类结构模式或对象结构模式
包含下列模式:
1)适配器模式
2)缺省适配器模式
3)合成模式
4)装饰模式
5)代理模式
6)享元模式
7)门面模式
8)桥梁模式
一、适配器模式
例子:指鹿为马
分为
1)类的适配器模式: 继承鹿类实现马的接口。
2)对象适配器模式: 关联关系,引用一个鹿的对象,完成马的接口。
二、默认适配器模式
没什么可注意的。就是做个抽象类,把接口的函数实现了,省的其每个派生类都要逐一完成。
三、合成模式
例子:资源管理器的文件、目录结构。
例子2:山、庙,老道,山、庙,老道。。。。
实现方法两种:
叶子节点和树枝节点都实现同一个接口。(透明式)
叶子使用叶子接口,树枝使用树枝接口。(安全式)
四、装饰模式
1)例子:孙悟空变身。 通过一个本尊,一会儿变鱼,再变鸟。
2)伪代码:
齐天大圣 c = new 大圣本尊()
齐天大圣 c1 = new 鱼(c);
齐天大圣 c2 = new 鸟(c1);
3)什么时候用:
类的增强用!这种增强比继承更灵活,因为使用继承后,父类和子类关系是固定的。即要满足IS关系。
但装饰模式更灵活,以上面的代码为例,鱼和齐天大圣不满足IS关系(鱼不是齐天大圣)。但通过装饰,在鱼类增加个swim()方法,就可以让孙猴子游泳了。
五、代理模式
用途:运用代理,可在真实角色执行前后,插入代码,执行特定操作!
1)远程代理:客户端使用该代理,可以认为代理对象是本地的,代理对象承担了大部分的网络通信工作。
2)虚拟代理:延迟加载,真正使用再加载。
3)保护代理:使用前,加权限检查。
4)智能引用代理:操作时统计。例如计数等。
注意点:代理角色和真实角色的接口要一致。客户端看不出二者的区别。(有一个统一的接口)
其余模式区别:
1)装饰:装饰增强,代理不增加,只是控制。
2)门面:有时候,门面兼有代理责任,例如检查调用者权限,记录访问次数等。这个时候叫做代理门面模式。
六、享元模式
例子:java的string类型和书上咖啡屋的例子。(注:书上复合享元对象的例子没太看懂,关注书上咖啡屋的例子即可。这个是单纯的享元对象。)
内蕴状态:咖啡屋例子中的咖啡风味。
外蕴状态:例子中,如果要跟踪咖啡送到哪一个桌位上,桌子号就是一个外蕴对象。
使用的场合:支持大量的细粒度对象。将这些对象分为可变部分(外蕴状态)和不可变部分(内蕴状态),工厂只需要创建不同的内蕴对象,调用函数时,外蕴状态通过参数传入,使用该模式可以少消耗大量的内存。
角色:除了客户端外,还有享元工厂角色(多例),抽象享元、具体享元。
复合享元模式中感觉用的场合不多, 不太重要。 它采用了合成模式,多了一个复合享元角色。复合享元角色管理一个聚集,记录内蕴聚合的key和value。工厂不光创建内蕴对象,还负责创建复合享元角色。
七、门面(Facade)模式
例子:ESB?,医院的接待员
使用门面模式,客户端只需要跟门面类打交道,至于具体调用到什么类上,客户端不需要知道。(门面模式要求一个子系统的外部与内部的通讯必须通过一个统一的门面。)
注意不要在门面类加上其他的新功能,它的用意就是为子系统提供一个集中化的沟通通道。
就像接待员不是医护人员,不能为患者提供医疗服务。
门面模式很好的体现出迪米特法则:每一个对象只和自己的朋友打交道,只要有可能,朋友的数目越少越好。
八、桥梁模式
例子:不同的飞机厂商制造不同的飞机。如果用继承关系,我们可能会有波音客机,波音直升机,波音战斗机,麦道客机,麦道直升机。。。。。这些类。
如果用桥梁关系就很容易解决了。
理解模式:用聚合关系将桥梁的两端联系起来,这样桥梁的两端就可以独自的变化(任意继承等级结构)。
例子说明:桥梁的一端的基类是飞机厂商,可以动态实例化一个任意的飞机厂商;桥梁的另一端的基类是飞机的种类,可以动态实例化任意一种飞机。他们用关联关系建立联系,这样就可以让任意的一个飞机厂商,创建一个任意种类的飞机。
注意点:桥梁之间之所以用聚合关系建立联系,因为聚合关系是一种弱关联。(编辑时期关系未确定)
而继承关系就是一个强关联。(编辑时期关系就已经确定了)
总结:一般情况,抽象化对象(桥梁的一端)是不需要变化的,实现化角色(另一端)是变化的。
但如果抽象化角色也要发生变化,这时候就应该使用桥梁模式。
另一个角度来看,好的设计继承关系不应该超过两层,如果层次太多了,应该考虑出有哪些变化因素,将动态的部分从继承关系改成聚合关系。(桥梁模式)