一、装饰者模式
1、定义
装饰者模式动态地将新功能附加上对象上。在对象扩展方面,比继承更有弹性,也体现了开闭原则。
2、原理类图
(1)Componet:主体
(2)ConcreateComponent:主体具体实现类
(3)Decorator:装饰者
(4)ConcreteDecorate:装饰者具体实现类
装饰者类和主体类继承同样的父类,这样就可以去主体类“嵌套”多个装饰者类。
3、案例
(1)背景介绍:
有一家咖啡店,店中有许多品种的咖啡(ShortBlack、Decaf、Espresso…),咖啡可以添加不同口味(Chocolate、Milk、Soy等),一般采用继承方式会导致类爆炸的问题,而采用装饰者模式可以很好的解决该问题。
比如,装饰者下单 (2份巧克力+1份牛奶+长黑咖啡)
(2)代码实现
public abstract class Drink {
private String des;//描述
private float price = 0.0f;
/**
* 计算价格的方法
* @return
*/
public abstract float cost();
public String getDes() {
return des;
}
public void setDes(String des) {
this.des = des;
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
}
public class Coffee extends Drink{
@Override
public float cost() {
return super.getPrice();
}
}
public class ShortBlack extends Coffee{
public ShortBlack() {
setDes("浓缩咖啡");
setPrice(4);
}
}
public class Espresso extends Coffee{
public Espresso() {
setPrice(6);
setDes("意大利咖啡");
}
}
public class LongBlack extends Coffee{
public LongBlack() {
setPrice(5);
setDes("美式咖啡");
}
}
public class Decorator extends Drink {
private Drink drink;
public Decorator(Drink drink) { // 组合
this.drink = drink;
}
@Override
public float cost() {
// 之前累计的drink价格 + 新装饰进来的drink价格
return super.getPrice() + drink.cost();
}
@Override
public String getDes() {
return super.getDes() + " && " + drink.getDes();
}
}
public class Chocolate extends Decorator{
public Chocolate(Drink drink) {
super(drink);
setDes("巧克力");
setPrice(3);
}
}
public class Milk extends Decorator{
public Milk(Drink drink) {
super(drink);
setDes("牛奶");
setPrice(2);
}
}
public class Soy extends Decorator{
public Soy(Drink drink) {
super(drink);
setDes("豆浆");
setPrice(1.5f);
}
}
public class CoffeeBar {
public static void main(String[] args) {
// 点一份咖啡
Drink order = new LongBlack();
System.out.println(order.cost() + "$\t" + order.getDes());
// 加一份牛奶
order = new Milk(order);
System.out.println(order.cost() + "$\t" + order.getDes());
// 加两份巧克力
order = new Chocolate(order);
System.out.println(order.cost() + "$\t" + order.getDes());
order = new Chocolate(order);
System.out.println(order.cost() + "$\t" + order.getDes());
}
}
4、应用
Java的IO结构,使用的就是装饰者模式,FilterInputStream就是一个装饰者类。