装饰器模式
-
定义:装饰器模式以对客户透明的方式动态的给一个对象附加上更多的责任。换言之,客户端并不会觉得对象在装饰前和装饰后有什么不同。
-
优点:1) 装饰模式与继承关系的目的都是要扩展对象的功能,但是装饰模式可以提供比继承更多的灵活性。2) 通过使用不同的具体装饰类以及这些装饰类的排列组合,设计师可以创造出很多不同行为的组合。
-
缺点:使用装饰模式会产生比使用继承关系更多的对象。更多的对象会使得查错变得困难,特别是这些对象看上去都很相像。
-
博客:https://www.jianshu.com/p/10a77d91c93f
-
实例:为星巴兹咖啡连锁店设计饮料菜单,咖啡可加的调料有豆浆、牛奶、摩卡等。可在咖啡的基础上加入不同的调料,星巴兹会根据所加的调料收取不同的费用,要注意到,以后可能有新的调料被加入进来供顾客选择。并且本店现有DarkRoast(深焙)、HouseBlend(综合)、Decaf(低咖啡因)及Espresso(浓咖啡)四种类型的咖啡,而且以后可能会添加新的咖啡种类。使用装饰者模式,四种咖啡为具体组件,调料为具体装饰者。
-
类图:
-
代码:
/**
* 抽象组件:需要装饰的抽象对象(接口或抽象父类) - 饮料
*/
abstract class Beverage {
private String description;
public Beverage(String description) {
this.description = description;
}
public String getDescription() {
return description;
}
public abstract double cost();
}
/**
* 具体组件:需要装饰的对象 - 无因咖啡
*/
class Decaf extends Beverage {
public Decaf() {
super("无因咖啡");
}
@Override
public double cost() {
return 1;
}
}
/**
* 具体组件:需要装饰的对象 - 焦糖咖啡
*/
class DarkRoast extends Beverage {
public DarkRoast() {
super("焦糖咖啡");
}
@Override
public double cost() {
return 3;
}
}
/**
* 具体组件:需要装饰的对象 - 浓缩咖啡
*/
class Espresso extends Beverage {
public Espresso() {
super("浓缩咖啡");
}
@Override
public double cost() {
return 2;
}
}
/**
* 具体组件:需要装饰的对象 - 混合咖啡
*/
class HouseBlend extends Beverage {
public HouseBlend() {
super("混合咖啡");
}
@Override
public double cost() {
return 1;
}
}
/**
* 抽象装饰类:包含了对抽象组件的引用以及装饰者共有的方法 - 调料
*/
abstract class Condiment extends Beverage {
//让调料类关联饮料类
protected Beverage beverage;
public Condiment(Beverage beverage) {
super("调料");
this.beverage = beverage;
}
}
/**
* 具体装饰类:被装饰的对象 - 牛奶
*/
class Milk extends Condiment {
public Milk(Beverage beverage) {
super(beverage);
}
@Override
public double cost() {
return beverage.cost() + 0.2;
}
@Override
public String getDescription() {
return beverage.getDescription() + " + 牛奶 ";
}
}
/**
* 具体装饰类:被装饰的对象 - 摩卡
*/
class Mocha extends Condiment {
public Mocha(Beverage beverage) {
super(beverage);
}
@Override
public double cost() {
return beverage.cost() + 0.4;
}
@Override
public String getDescription() {
return beverage.getDescription() + " + 摩卡 ";
}
}
/**
* 具体装饰类:被装饰的对象 - 豆浆
*/
class Soy extends Condiment {
public Soy(Beverage beverage) {
super(beverage);
}
@Override
public double cost() {
return beverage.cost() + 0.3;
}
@Override
public String getDescription() {
return beverage.getDescription() + " + 豆浆 ";
}
}
/**
* 测试装饰器
*/
public class TestDecorator {
public static void main(String[] args) {
Beverage b1 = new Decaf();
Beverage b2 = new Milk(b1);
Beverage b3 = new Mocha(b2);
Beverage b4 = new Soy(b3);
Beverage b5 = new Soy(b4);
System.out.println(b5.getDescription() + b5.cost());
}
}