23种设计模式----装饰器模式----结构型模式
原创
©著作权归作者所有:来自51CTO博客作者qq5963a5404b339的原创作品,请联系作者获取转载授权,否则将追究法律责任
装饰器模式
23种设计模式
1.什么是装饰器模式
(图片来自W3Cschool,如有需要,联系删除)
2.装饰器模式的结构图
实现
继承
实现
关联
具体的被装饰物
抽象的被装饰物
抽象的装饰物
具体的装饰物
3.装饰器的核心点
3.1 装饰器的被装饰物的接口“透明”
首先,什么是接口透明?
接口透明是指被装饰物被装饰物装饰后,被装饰物本身不发生任何变化,其接口或者方法仍可以被外界调用,与未装饰之前无改变。
3.3 装饰器模式中思想是委托
其实我们不管如何的使用装饰器模式,有一个点不会变,那就是装饰器模式的本质是被装饰物,装饰物装饰被装饰物是为了突出被装饰物。有点绕口,可以这么理解:
你家里买了新房子,装修是为了好看。但是不管如何装修,有一个共同的目的:房子好看舒服。。。。。
但是,本质上一个房子好看,舒服,以及其他的要求,应该是对房子主体提出的要求,但是我们通过装修实现。这样就完成了一个委托。
把对房子的要求委托给装修。
即,被装饰物需要实现的功能,通过装饰器模式委托给装饰物。
3.2 装饰器模式中的递归
因为抽象的装饰物必须与装饰物装饰的被装饰物的类型绑定,说的简单一点,床放在卧室,沙发放在客厅一样。
抽象的装饰物通过持有抽象的被装饰物,而这个抽象的被装饰物可以看做一个类型,当类型没有限制,就是所有的被装饰物。
抽象的装饰物一方面持有抽象的被装饰物,另一方面具体的装饰物和具体的被装饰物拥有相同的方法,所以,调用具体的装饰物的方法会递归调用所有参数本次构造的具体的装饰物,具体的被装饰物的方法。
3.3 委托
打个比方:
有A,B两个类,现在需要A实现一个do方法,但是A不想实现do方法,于是委托给B,让B去实现:
A.do{
B.do();
}
(这不是真正的编程语法,只是举个例子)
B.do{
//…
}
这样可以看出,A把do方法委托给了B
前提条件就是A可以访问B的do方法,或者A持有B的实例。
A与B之间是弱关联。
这是通过直接关联实现委托。
还有间接关联实现委托。
首先,我们观察直接关联实现委托,发现A和B类中有一个共同点:
都有do方法,且方法申明完全相同。
那么就可以把这部分抽象出一个接口或者抽象类
然后让A和B继承于或者实现接口或者抽象类
然后让委托类持有基类的对象调用抽象的方法。
比较:
间接委托实现一对多委托,动态委托
直接委托只能实现一对一委托
4.例子
项目的结构:
说明:
Client中使用装饰物或者被装饰物的类
compoment中是被装饰物
decorator中是装饰物
abs中是抽象
impl中是实现
下面的代码中注意包结构
4.1抽象的被装饰物–房子
package decorator.component.abs;
/**
* 被装饰物的抽象,如果有抽象出的属性,使用抽象类
*
*/
public interface House {
public void say();
}
4.2 具体的被装饰物–大房子
package decorator.component.impl;
import cn.com.startimes.decorator.component.abs.House;
/**
* 具体的被装饰物--大房子
*
*/
public class BigHouse implements House{
@Override
public void say() {
System.out.println("我是大房子");
}
}
4.3 抽象的装饰物–家具
package decorator.decorator.abs;
import cn.com.startimes.decorator.component.abs.House;
/**
* 抽象的装饰物--家具
*
*/
public abstract class Furniture implements House{
/**
* 装饰物装饰的对象类型(注意这里可以按照类型来理解)
*/
protected House house;
/**
* 家具被造出来大致就确定了在某一个房子发挥作用
*/
public Furniture(House house) {
super();
this.house = house;
}
@Override
public abstract void say();
}
4.4 具体的被装饰物–床
package decorator.decorator.impl;
import cn.com.startimes.decorator.component.abs.House;
import cn.com.startimes.decorator.decorator.abs.Furniture;
/**
* 具体的装饰物----家具
*
*/
public class Bed extends Furniture{
public Bed(House house) {
super(house);
}
@Override
public void say() {
super.house.say();
System.out.println("我是家具--床");
}
}
4.5 使用
package decorator.client;
import cn.com.startimes.decorator.component.abs.House;
import cn.com.startimes.decorator.component.impl.BigHouse;
import cn.com.startimes.decorator.decorator.impl.Bed;
import cn.com.startimes.decorator.decorator.impl.Chair;
public class Main {
public static void main(String[] args) {
House house = new BigHouse();
System.out.println("house:");
house.say();
System.out.println();
System.out.println("Bed:");
House bed = new Bed(house);
bed.say();
}
}
4.6 结果
house:
我是大房子
Bed:
我是大房子
我是家具--床
4.7 扩充–椅子
package decorator.decorator.impl;
import cn.com.startimes.decorator.component.abs.House;
import cn.com.startimes.decorator.decorator.abs.Furniture;
public class Chair extends Furniture{
public Chair(House house) {
super(house);
}
@Override
public void say() {
super.house.say();
System.out.println("我是家具--椅子");
}
}
4.8 使用
package decorator.client;
import cn.com.startimes.decorator.component.abs.House;
import cn.com.startimes.decorator.component.impl.BigHouse;
import cn.com.startimes.decorator.decorator.impl.Bed;
import cn.com.startimes.decorator.decorator.impl.Chair;
public class Main {
public static void main(String[] args) {
House house = new BigHouse();
System.out.println("house:");
house.say();
System.out.println();
System.out.println("Bed:");
House bed = new Bed(house);
bed.say();
System.out.println();
System.out.println("ChairForHouse:");
House chair = new Chair(new Bed(house));
chair.say();
System.out.println();
System.out.println("ChairForBed:");
House chairBed = new Chair(new Bed(bed));
chairBed.say();
System.out.println();
System.out.println("ChairForChair:");
House chairChair = new Chair(chair);
chairChair.say();
System.out.println();
System.out.println("BigHouse:");
house.say();
}
}
4.9 结果
house:
我是大房子
Bed:
我是大房子
我是家具--床
ChairForHouse:
我是大房子
我是家具--床
我是家具--椅子
ChairForBed:
我是大房子
我是家具--床
我是家具--床
我是家具--椅子
ChairForChair:
我是大房子
我是家具--床
我是家具--椅子
我是家具--椅子
BigHouse:
我是大房子
说明:
house -------- bed ------委托+透明
chairForHouse --------- chairForBed ------- 递归+委托+透明(递归Bed)
chairForHouse --------- chairForChar--------递归+委托+透明(递归Chair)
BigHouse---------透明性