适配器
目标角色(Target):该角色定义把其他类转换为何种接口,也就是我们的期望接口。
源角色(Adaptee):你想把谁转换成目标角色,这个“谁”就是源角色,它是已经存在的、运行良好的类或对象。
适配器角色(Adapter):适配器模式的核心角色,其他两个角色都是已经存在的角色,而适配器角色是需要新建立的,它的职责非常简单:通过继承或是类关联的方式把源角色转换为目标角色。
通过继承实现的类适配器和通过组合实现的对象适配器,这样通过适配器C在使用A的接口中实际引入了B的功能。
开闭原则:解耦目标类和适配类,在不更改原代码的情况下,想适配什么接口直接增加新的适配器。
核心:增设继承于A类的适配类C,利用多态篡改A类接口。把B类传给C类,通过C完成B篡权的野心。即外族B要篡权,借助了传口谕的太监C,篡夺了A的皇权。
使用了多态的函数覆盖,违背里氏替换原则。为了适配B类的某一接口引入了整个B类,违背了单一性原则。
WildTurkey turkey = new WildTurkey();
Duck duck = new TurkeyAdapter(turkey);
duck.quack();//通过duck表现出了turkey 的特点
duck.fly();
装饰
抽象组件角色(Component):定义一个对象接口,以规范准备接受附加责任的对象,即可以给这些对象动态地添加职责。
具体组件角色(ConcreteComponent) :被装饰者,定义一个将要被装饰增加功能的类。可以给这个类的对象添加一些职责。
抽象装饰器(Decorator):维持一个指向构件Component对象的实例,并定义一个与抽象组件角色Component接口一致的接口。
具体装饰器角色(ConcreteDecorator):向组件添加职责。
开闭原则:一个主料作为一个ConcreteComponent,对应有一个抽象装饰者Decorator, 组件的每种具体配料作为一个具体装饰者,每增加一种配料就增加一个具体装饰者。
核心:首先装饰者必须类属于主料类型,只有同一种类型才可以装饰。其次把主料聚合到辅料里面来形成一个新的主料,然后再可以把新的主料聚合到下一个辅料中形成另一个新的主料,不断叠加,最后从新的主料里面出账。
装饰者模式是很巧妙的组合方式,如果不使用装饰者模式,那么每一种辅料和主料的组合,辅料和辅料组合之后再和主料组合,每添加一种辅料都会有无数种组合,每一种组合都是一个新的类,那就会有很多的类,导致类膨胀。
外观
桥接
有两岸才有桥。两个不内聚的体系通过桥接来实现松散耦合,其所要表现的是接口隔离原则。
每个接口各成一个体系,2个接口体系可自由变化相互不影响。
通过桥接,2个体系下的对象可自由组合实现不同的功能产生不同的效果。
核心:把2个相关联的事物用2套接口实现,然后再在接口层聚合实现弱关联。
这是比较常用的一种设计模式,使用桥接保证2个体系可自由扩展,相互之间的修改不相互影响。
这个桥还是一个简单的set函数。
Pen pen = new BigPen();
Color clr = new Red();
pen.setColor(clr);
pen.draw();
使用上有点像策略模式,但策略模式涉及不到两个体系的变化,策略模式只是针对一个体系中,通过set不同的算法来实现不同的功能。
代理
享元
单纯从接口看就是一个创建工厂,带缓存(内存池)的创建工厂,属于创建型模式。
如果非要作为结构型,那就需要把非享元角色算上。非享元能够表示对外的一个个对象,使用到享元时获取享元并把非享元作为参数注入到享元中使用。如棋盘的黑子白子,作为享元只创建2个享元对象,但棋盘中的无数个棋子需要通过非享元对象坐标+享元对象棋子来共同表示。
核心:分离变与不变。为不变设计一个类,变的设计另一个类,通过这2个分开的类的组合实现不分开的整体功能。
从设计原则上看,符合工厂模式创建时的开闭原则,至于通过缓存对象来节省内存开支,这个不在设计原则中。为了节省内存开支通过缓存池来实现这是任何开发者都容易想到的实现方式,所以这一点只能算是一个通用简单的实现方法。
组合
适用于局部和整体按统一标准处理的场景,如树形结构,容器界面,目录结构等。
局部和整体(树叶和树枝)继承统一标准的接口,client针对接口使用,不区分是局部或是整体。(如果不用组合模式则client需要区别对待叶子节点和非叶子节点,并且还要区分不同类型的叶子节点对应有哪些不一样的操作)
局部和整体继承接口后,支持的功能就实现接口,不支持的空实现或者排除不支持的提示。(违背接口隔离和单一性原则)
非叶子节点作为容器节点,里面有个list,可以不断地往里面添加子节点。(添加的子节点可以是叶子节点也可以是非叶子节点,因为都继承自标准接口所以叶子和非叶子同属一个类型)
需要增加新的节点时,只需继承接口完成自己的节点类就行,符合开闭原则。client使用的时候按统一标准使用。(如果不适用组合模式,每增加新的节点都需要修改原有代码来增加,不符合开闭原则)
核心:局部和整体统一接口,存在add接口,相互容纳。