装饰者模式:
动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。
问题:继承与组合的特点?
继承:利用继承设计子类的行为,是在编译时静态决定的,而且所有的子类都会继承到相同的行为。
组合:利用组合的做法扩展对象的行为,就可以在运行时动态地进行扩展。这里的装饰者模式就运用到这种组合的思想。
举个栗子:
星巴克咖啡店有这几种饮料:浓咖啡espresso、黑暗烤肉darkroast、屋混合houseblend,这几种饮料可以随意添加这几种调料:摩卡mocha、奶油whip、大豆soy,上面的饮料可以任意添加各种调料,程序中需要给出饮料对于的任意的调料名,且饮料和调料都有其价格,需要给出饮料添加调料后的价格。
思路: 利用装饰者模式
定义饮料的抽象类:
Beverage.java 类:
public abstract class Beverage {
String description = "Unknown Beverage";
public String getDescription(){
return description;
}
public abstract double cost();
}
三个具体的饮料:浓咖啡espresso、黑暗烤肉darkroast、屋混合houseblend,继承上述Beverage.java类,其代码如下:
Espresso.java 类:
public class Espresso extends Beverage {
public Espresso(){
description = "Espresso";
}
@Override
public double cost() {
return 1.99;
}
}
DarkRoast.java 类:
public class DarkRoast extends Beverage {
public DarkRoast(){
description = "dark roast";
}
@Override
public double cost() {
return 1.22;
}
}
HouseBlend.java 类:
public class HouseBlend extends Beverage {
public HouseBlend(){
description = "House Blend Coffee";
}
@Override
public double cost() {
return .89;
}
}
定义装饰者的抽象类:
CondimentDecorator.java 类:
public abstract class CondimentDecorator extends Beverage {
public abstract String getDescription();
}
这里:将继承中的Beverage类中getDescription(),并将其覆盖重新定义了一个抽象类getDescription();
三种调料装饰者:摩卡mocha、奶油whip、大豆soy的具体实现类如下:
Mocha.java 类:
public class Mocha extends CondimentDecorator {
Beverage beverage;
public Mocha(Beverage beverage){
this.beverage = beverage;
}
@Override
public String getDescription() {
return beverage.getDescription() + ", Mocha";
}
@Override
public double cost() {
return .20 + beverage.cost();
}
}
Whip.java 类:
public class Whip extends CondimentDecorator {
Beverage beverage;
public Whip(Beverage beverage){
this.beverage = beverage;
}
@Override
public String getDescription() {
return beverage.getDescription() + ", Whip";
}
@Override
public double cost() {
return .11 + beverage.cost();
}
}
Soy.java 类:
public class Soy extends CondimentDecorator {
Beverage beverage;
public Soy(Beverage beverage){
this.beverage = beverage;
}
@Override
public String getDescription() {
return beverage.getDescription() + ", Soy";
}
@Override
public double cost() {
return .33 + beverage.cost();
}
}
----------------------------------------我是华丽的分割线-----------------------------------------
具体实际调用的例子如下:
StarbuzzCoffee.java 类:
public class StarbuzzCoffee {
public static void main(String[] args) {
Beverage beverage = new Espresso();
System.out.println(beverage.getDescription() + " $" + beverage.cost());
Beverage beverage2 = new DarkRoast();
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());
}
}
输出结果如下:
Espresso $1.99
dark roast, Mocha, Mocha, Whip $1.73
House Blend Coffee, Soy, Mocha, Whip $1.53
分析:
装饰者模式,主要是在装饰者类中将被装饰对象当成字段属性,然后覆写被装饰对象的某些方法,在实际调用的时候将被装饰对象传入装饰对象即可,如下:
Beverage beverage3 = new HouseBlend();
beverage3 = new Soy(beverage3);
beverage3 = new Mocha(beverage3);
beverage3 = new Whip(beverage3);