装饰者模式的使用场景:
在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。
需要动态地给一个对象增加功能,这些功能也可以动态地被撤销。
当不能采用继承的方式对系统进行扩充或者采用继承不利于系统扩展和维护时。不能采用继承的情况主要有两类:第一类是系统中存在大量独立的扩展,为支持每一种组合将产生大量的子类,使得字类数目呈爆炸性增长;第二类是因为定义不能继承(入final类)
1、角色
1.1、抽象构建角色(Component):定义一个对象接口或者抽象类,可以给这些对象动态地添加职责。
1.2、具体构建角色(ConcreteComponent):实际被动态地添加职责的对象。
1.3、抽象装饰者角色(Decorator):实现了Component接口,用来扩展Component类的功能,但是对于Component来说,是无需知道Decorator的存在的。
1.4、具体装饰者角色(ConcreteDecorator):动态地添加职责的对象。
2、代码实现
2.1、抽象构件角色
public interface Man {
public void getManDesc();
}
2.2、具体构件角色
public class NormalMan implements Man {
private String name = null;
public NormalMan(String name){
this.name = name;
}
@Override
public void getManDesc() {
System.out.print(name + ": ");
}
}
2.3、抽象装饰者角色
public abstract class AttachedPropertiesDecorator implements Man {
private Man man;
public AttachedPropertiesDecorator(Man man){
this.man = man;
}
public void getManDesc() {
man.getManDesc();
}
}
2.4、具体装饰者角色
//车子装饰者
public class CarDecoratorImpl extends AttachedPropertiesDecorator {
private String car = "有车";
public CarDecoratorImpl(Man man) {
super(man);
}
public void addCar(){
System.out.print(car + " ");
}
@Override
public void getManDesc() {
super.getManDesc();
addCar();
}
}
//房子装饰者
public class HouseDecoratorImpl extends AttachedPropertiesDecorator {
private String house = "有房";
public HouseDecoratorImpl(Man man) {
super(man);
}
public void addHouse(){
System.out.print(house + " ");
}
@Override
public void getManDesc() {
super.getManDesc();
addHouse();
}
}
//存款装饰者
public class DepositDecoratorImpl extends AttachedPropertiesDecorator {
private String deposit = "有存款";
public DepositDecoratorImpl(Man man) {
super(man);
}
public void addDeposit(){
System.out.print(deposit + " ");
}
@Override
public void getManDesc() {
super.getManDesc();
addDeposit();
}
}
2.5、装饰者模式测试类
public class DecoratorTest {
public static void main(String[] args) {
Man man = new NormalMan("张三");
man.getManDesc();
Man man1 = new CarDecoratorImpl(man);
Man man2 = new HouseDecoratorImpl(man1);
System.out.println("层层装饰:");
man2.getManDesc();
System.out.println();
System.out.println("重复装饰(有两个'有房')");
Man man3 = new HouseDecoratorImpl(man2);
man3.getManDesc();
System.out.println();
System.out.println("任意修饰:");
Man man4 = new DepositDecoratorImpl(man1);
man4.getManDesc();
System.out.println();
System.out.println("直接得到修饰结果:");
Man man5 = new HouseDecoratorImpl(new DepositDecoratorImpl(new NormalMan("李四")));
man5.getManDesc();
System.out.println();
}
}
调用的链路:
1、在调用man2.getManDesc()中首先找到的是HouseDecoratorImpl的getManDesc方法
2、在HouseDecoratorImpl的getManDesc方法之前调用的是父类的getManDesc,父类中的AttachedPropertiesDecorator的man存储的是CarDecoratorImpl对象,
所以调用的就是CarDecoratorImpl的getManDesc方法。
3、就一直往下进行调用,就实现了装饰者模式