Java I/O系统中的类的设计,大量使用了装饰者模式,所以理解装饰者模式,对于理解I/O流的设计来说,十分重要。
装饰者模式:动态的将责任附加到对象上。若要扩展功能,装饰者提供了比继承更具有弹性的替代方案。
星巴克咖啡:星巴克提供了四种口味的咖啡:HouseBlend ,DarkRoast,Decaf,Espresso
顾客购买了一种口味的咖啡之后,可以要求往咖啡里加入调料:SteamedMilk (蒸奶) , Soy(豆浆) ,Mocha(摩卡),Whip(奶泡)。
星巴克根据不同的调料收取不同的费用 , 一杯咖啡的总花费是 咖啡+调料
设计原则:类应该对扩展开放,对修改关闭。允许类容易扩展,在不修改现有代码的情况下,就可搭配新的行为。
我们以饮料为主体,然后在运行时以调料来“装饰”饮料。比如,如果顾客想要DarkRoast咖啡,加入Mocha和Whip:
1.拿一个DarkRoast咖啡对象;
2.以Mocha对象装饰它;
3.以Whip对象装饰它;
4.调用cost()方法,并依赖委托(delegate)将调料的价钱加上去。
Mocha,Whip称为装饰者,DarkRoast称为被装饰者。 装饰者和被装饰者必须是一样的类型,也就是有共同的超类,因为最终装饰之后的对象,必须能够取代最初的被装饰者对象。
全局类的结构:
Beverage超类:
public abstract class Beverage { protected String description = "Unknown Beverage"; public String getDescription() { return description; } public abstract double cost(); }
CondimentDecorator类:
public abstract class CondimentDecorator extends Beverage { public abstract String getDescription(); }
具体实现类:
咖啡相关的类:
public class HouseBlend extends Beverage { public HouseBlend() { this.description = "HouseBlend"; } @Override public double cost() { return 1.99; } } public class DarkRoast extends Beverage { public DarkRoast() { this.description = "DarkRoast"; } @Override public double cost() { return 2.99; } } public class Decaf extends Beverage { public Decaf() { this.description = "Decaf"; } @Override public double cost() { return 3.99; } } public class Espresso extends Beverage { public Espresso() { this.description = "Espresso"; } @Override public double cost() { return 4.99; } }
调料相关的类:
public class Mocha extends CondimentDecorator { public Beverage beverage; public Mocha(){} public Mocha(Beverage beverage) { this.beverage = beverage ; } @Override public String getDescription() { return beverage.getDescription() + ",Mocha"; } @Override public double cost() { return 0.20 + beverage.cost(); } } public class Whip extends CondimentDecorator { public Beverage beverage; public Whip(){} public Whip(Beverage beverage) { this.beverage = beverage; } @Override public String getDescription() { return beverage.getDescription()+",Whip"; } @Override public double cost() { return 0.50 + beverage.cost(); } }
最后 ,写个一个测试类:
public class TestClass { public static void main(String[] args) { Beverage beverage = new DarkRoast(); beverage = new Mocha(beverage); beverage = new Whip(beverage); System.out.println(beverage.getDescription() + " $" + beverage.cost()); //上面的写法类同与下面的写法: //Beverage beverage = new Whip(new Mocha(new DarkRoast())); //System.out.println(beverage.getDescription() + " $" + beverage.cost()); Beverage beverage2 = new DarkRoast(); beverage2 = new Mocha(beverage2); beverage2 = new Mocha(beverage2); //需要双份的Mocha就 两次包装 beverage2 = new Whip(beverage2); System.out.println(beverage2.getDescription() + " $" + beverage2.cost()); } }
运行结果: