装饰者模式
装饰者模式:动态的将新功能附加到对象上,在对象功能扩展方面,他比继承更有弹性,装饰者模式也体现了开闭原则(OCP)。
代码:计算一个两份巧克力+一份牛奶+一份美式咖啡的价格
public abstract class Drink {
private String des;
private float price = 0.0f;
public String getDes() {
return des;
}
void setDes(String des) {
this.des = des;
}
float getPrice() {
return price;
}
void setPrice(float price) {
this.price = price;
}
public abstract float cost();
}
/**
* 被装饰者的共同点抽象
*/
public class Coffee extends Drink{
@Override
public float cost() {
return super.getPrice();
}
}
public class Espresso extends Coffee {
public Espresso() {
setDes("意大利咖啡");
setPrice(6.0f);
}
}
public class LongBlack extends Coffee {
public LongBlack() {
setDes("美式咖啡");
setPrice(5.0f);
}
}
public class ShortBlack extends Coffee{
public ShortBlack() {
setDes("short black");
setPrice(4.0f);
}
}
/**
* 装饰者类
*/
public class Decorator extends Drink {
private Drink drink;
Decorator(Drink drink) {
this.drink = drink;
}
@Override
public float cost() {
//super.getPrice()为自己单品的价格
//drink为之前组合的所有单品的价格
return super.getPrice() + drink.cost();
}
@Override
public String getDes() {
return super.getDes() + "" + super.getPrice() + "&&" + drink.getDes();
}
}
/**
* 具体的装饰者,这里就是单品
*/
class Chocolate extends Decorator{
Chocolate(Drink drink) {
super(drink);
setDes("巧克力");
setPrice(1.0f);
}
}
public class Milk extends Decorator {
public Milk(Drink drink) {
super(drink);
setDes("牛奶");
setPrice(2.0f);
}
}
public class Soy extends Decorator {
public Soy(Drink drink) {
super(drink);
setDes("豆浆");
setPrice(0.5f);
}
}
public class Client {
public static void main(String[] args) {
//装饰者模式下订单:两份巧克力+一份牛奶的longBlack
Drink order = new LongBlack();
//加入一份牛奶
order = new Milk(order);
System.out.println("咖啡组合名:" + order.getDes());
System.out.println("咖啡总价:" + order.cost());
//加入一份巧克力
order = new Chocolate(order);
System.out.println("咖啡组合名:" + order.getDes());
System.out.println("咖啡总价:" + order.cost());
//在加入一份巧克力
order = new Chocolate(order);
System.out.println("咖啡组合名:" + order.getDes());
System.out.println("咖啡总价:" + order.cost());
}
}
装饰者模式实现,使单个产品组合和方便,扩展性更好,当新增咖啡类型和调料的时候只需要继承coffee和Decorator就可以实现扩展,特别方便。
源码案例:java的IO结构,FilterInputStream就是一个装饰者。
装饰器模式的应用场景:
1、需要扩展一个类的功能;
2、动态的为一个对象增加功能,而且还能动态撤销。(继承不能做到这一点,继承的功能是静态的,不能动态增删。)
缺点:产生过多相似的对象,不易排错!