装饰者模式(the Decorator Pattern)
动态地将责任附加在对象上。若有扩展功能,装饰者提供了比继承更有弹性的替代方案。
以咖啡厅为例,当仅仅是对父类Beverage继承时,如果子类需要增加新的调料,那么子类的数量会迅速增大,造成管理和维护上的困难。如果调料的种类有变化的时候,子类也要进行相应的修改。这样就违反了设计原则:类应该对修改关闭,对扩展开放。因此我们要引入装饰者模式,对饮料进行一层层的调料装饰。
现在来看看具体的例子:
1.设计Beverage父类:
2.调料抽象类
public
abstract
class
Beverage
...
{
String description = "Unknown Beverage";
public String getDescription() ...{
return description;
}
public abstract double cost();
}
String description = "Unknown Beverage";
public String getDescription() ...{
return description;
}
public abstract double cost();
}
public
abstract
class
CondimentDecorator
extends
Beverage
...
{
public abstract String getDescription();
}
public abstract String getDescription();
}
3.具体的饮料
public class Espresso extends Beverage...
{
public Espresso() ...{
description = "Escpresso";
}
public double cost() ...{
return 1.99;
}
}
public class HouseBlend extends Beverage ... {
public HouseBlend() ...{
description = "House Blend Coffee";
}
public double cost() ...{
return .99;
}
}
public Espresso() ...{
description = "Escpresso";
}
public double cost() ...{
return 1.99;
}
}
public class HouseBlend extends Beverage ... {
public HouseBlend() ...{
description = "House Blend Coffee";
}
public double cost() ...{
return .99;
}
}
4.具体的调料
public class Soy extends CondimentDecorator ...
{
Beverage beverage;
public Soy(Beverage beverage)...{
this.beverage = beverage;
}
@Override
public String getDescription() ...{
return beverage.getDescription() + ",Soy";
}
public double cost()...{
return .34 + beverage.cost();
}
}
public class Mocha extends CondimentDecorator ... {
Beverage beverage;
public Mocha(Beverage beverage) ...{
this.beverage = beverage;
}
@Override
public String getDescription() ...{
return beverage.getDescription() + ", Mocha";
}
public double cost()...{
return .20 + beverage.cost();
}
}
public class Whip extends CondimentDecorator ... {
Beverage beverage;
public Whip(Beverage beverage)...{
this.beverage = beverage;
}
@Override
public String getDescription() ...{
return beverage.getDescription() + ",Whip";
}
public double cost() ...{
return .78 + beverage.cost();
}
}
Beverage beverage;
public Soy(Beverage beverage)...{
this.beverage = beverage;
}
@Override
public String getDescription() ...{
return beverage.getDescription() + ",Soy";
}
public double cost()...{
return .34 + beverage.cost();
}
}
public class Mocha extends CondimentDecorator ... {
Beverage beverage;
public Mocha(Beverage beverage) ...{
this.beverage = beverage;
}
@Override
public String getDescription() ...{
return beverage.getDescription() + ", Mocha";
}
public double cost()...{
return .20 + beverage.cost();
}
}
public class Whip extends CondimentDecorator ... {
Beverage beverage;
public Whip(Beverage beverage)...{
this.beverage = beverage;
}
@Override
public String getDescription() ...{
return beverage.getDescription() + ",Whip";
}
public double cost() ...{
return .78 + beverage.cost();
}
}
5.具体应用测试
public
class
StarbuzzCoffee
...
{
public static void main(String[] args) ...{
Beverage beverage = new Espresso();
System.out.println(beverage.getDescription() + "$" + beverage.cost());
Beverage beverage2 = new Espresso();
//用调料来装饰饮料
beverage2 = new Mocha(beverage2);
beverage2 = new Mocha(beverage2);
beverage2 = new Whip(beverage2);
System.out.println(beverage2.getDescription() + "$" + beverage2.cost());
Beverage beverage3 = new HouseBlend();
beverage3 = new Soy(beverage3);
beverage3 = new Mocha(beverage3);
beverage3 = new Whip(beverage3);
System.out.println(beverage3.getDescription() + "$" + beverage3.cost());
}
}
public static void main(String[] args) ...{
Beverage beverage = new Espresso();
System.out.println(beverage.getDescription() + "$" + beverage.cost());
Beverage beverage2 = new Espresso();
//用调料来装饰饮料
beverage2 = new Mocha(beverage2);
beverage2 = new Mocha(beverage2);
beverage2 = new Whip(beverage2);
System.out.println(beverage2.getDescription() + "$" + beverage2.cost());
Beverage beverage3 = new HouseBlend();
beverage3 = new Soy(beverage3);
beverage3 = new Mocha(beverage3);
beverage3 = new Whip(beverage3);
System.out.println(beverage3.getDescription() + "$" + beverage3.cost());
}
}
这样做的好处在于:
1. 增加,修改调料的时候,不会影响其他的类
2. 功能作用划分清晰,利于管理
在java.io包中,就用了很多这样的模式。