装饰者模式
装饰者模式:动态的将额外的责任添加到对象上去,相对于继承,提供更加灵活的扩展方案。
装饰者模式,有4个抽象的类概念:
- 抽象构建类:被装饰对象的接口
- 具体的构建类:被装饰的对象
- 抽象装饰者:怎么进行装饰的接口
- 具体装饰者:具体装饰的对象
关系类图如下:
其中重点是:抽象装饰者接口继承了被装饰对象的接口,这点非常重要,它是能够进行动态装饰的关键,根据接口动态的去匹配具体构件类。
举例:
咖啡店原本提供有2种咖啡:CoffeeDarked深焙咖啡、CoffeeMixed混合咖啡,先需要在这2中咖啡中可以添加:Milk牛奶、Mocha摩卡。
思考:
按照上图分析结果,可以调出6中不同口味的咖啡。如果按照继承的逻辑,一种咖啡可能需要建立一个子类(或者实现类),此处就需要建6个子类。如果需要添加的不止牛奶和摩卡2种,那子类将非常庞大。
如果使用装饰者模式,就不需要建立6个子类,只需要建立2种具体装饰者类(Milk、Mocha),即可满足需求。
下面是代码实现:()
1)抽象构件类
/**
* 抽象构件类
* @author Administrator
*
*/
public interface Coffee {
/**
* 描述什么样的咖啡
* @return
*/
public abstract String getDescription();
/**
* 计算咖啡的价格
* @return
*/
public abstract double count();
}
2)具体构件类
/**
* 具体构件类:深焙咖啡
* @author Administrator
*
*/
public class CoffeeDarked implements Coffee {
@Override
public String getDescription() {
return "深焙咖啡";
}
@Override
public double count() {
return 10;
}
}
/**
* 具体构建类:混合咖啡
* @author Administrator
*
*/
public class CoffeeMixed implements Coffee {
@Override
public String getDescription() {
return "混合咖啡";
}
@Override
public double count() {
return 20;
}
}
3)抽象装饰者类
/**
* 咖啡装饰者接口
* @author Administrator
*
*/
public interface DecoratorCoffee extends Coffee {
public abstract String getDescription();
}
4)具体装饰者类
/**
* 具体装饰者:加牛奶
* @author Administrator
*
*/
public class DecoratorMilk implements DecoratorCoffee {
private Coffee coffee;
public DecoratorMilk(Coffee coffee){
this.coffee = coffee;
}
@Override
public double count() {
return coffee.count() + 5;
}
@Override
public String getDescription() {
return coffee.getDescription() + "加牛奶";
}
}
/**
* 具体装饰者类:加摩卡
* @author Administrator
*
*/
public class DecoratorMocha implements DecoratorCoffee {
private Coffee coffee;
public DecoratorMocha(Coffee coffee){
this.coffee = coffee;
}
@Override
public String getDescription() {
return coffee.getDescription() + "加摩卡";
}
public double count() {
return coffee.count() + 2;
}
}
最后测试下:
public class DecoratorTest {
/**
* @param args
*/
public static void main(String[] args) {
//想要一杯混合咖啡
Coffee coffee1 = new CoffeeMixed();
System.out.println(coffee1.getDescription() + " " + coffee1.count());
// 想要一杯加牛奶的混合咖啡(对coffee1进行装饰,加上牛奶)
Coffee coffee2 = new DecoratorMilk(coffee1);
System.out.println(coffee2.getDescription() + " " + coffee2.count());
// 想要一杯加摩卡加牛奶的深焙咖啡
Coffee coffee3 = new CoffeeDarked();
coffee3 = new DecoratorMilk(coffee3);
coffee3 = new DecoratorMocha(coffee3);//进一步对加了牛奶的咖啡加上摩卡
System.out.println(coffee3.getDescription() + " " + coffee3.count());
}
}
测试结果:
总结:
装饰者模式能实现动态的对对象进行扩展,主要有2点,一是,抽象装饰者类和具体的构建类有相同的接口,二是具体的装饰者类和抽象构建类之间有依赖(具体在UML中怎么称呼不太了解,之后在补习下),并且通过构造器依赖注入,在运行时,就根据具体的实现类注入了。这样就实现了对象动态扩展。
装饰者模式和代理模式的区别:
代理模式:给对象创建一个代理对象,由代理对象代替对象进行操作。
装饰者模式:对对象进行功能的扩展。