三.装饰者模式
首先来看一个例子:星巴克的点单系统
首先咖啡有分类:浓缩,拿铁,美式,摩卡等等,每种都有一个固定价格。
在这个基础上,我们可以选择,蒸奶,豆浆,摩卡,有一些附加的价格。
这样的话,我们如何设计类来计算价格呢,显然每种排列加一个类来确定价格不合适,况且还会出现加两分豆浆的情况。
在正式设计的时候,首先讲一个原则:开放关闭原则。
类应该是对扩展开放,对修改关闭。
设计理念是:先拿一种饮料作为主体,然后拿调料来装饰他。
步骤:
1. 拿一个深焙咖啡(DarkRoast)对象
2. 以摩卡(Mocha)对象装饰它
3. 以奶泡(Whip)对象装饰它
4. 调用cost()方法,并依赖委托深焙咖啡将调料的价格加上去。
具体实装:
饮料的抽象类:
publicabstractclass Beverage {
//
String description = "unkown beverage";
//
public String getDescription(){
returndescription;
}
//
publicabstractdouble cost();
}
调料的抽象类,也就是装饰类。
publicabstractclass Condiment extends Beverage{
//
publicabstract String getDescription();
}
具体咖啡种类的类,如浓缩咖啡:
publicclass Espresso extends Beverage{
public Espresso(){
description = "Espresso";
}
//
@Override
publicdouble cost() {
return 1.99;
}
}
下面开始实装调料的代码:(摩卡)
publicclass Mocha extends Condiment {
//用来放作为参数的起始对象,如种类咖啡,或是已经被装饰过的咖啡
public Beverage beverage;
//
public Mocha(Beveragebeverage) {
this.beverage = beverage;
}
//
public StringgetDescription() {
returnbeverage.getDescription() + ",mocha";
}
//
publicdouble cost() {
return 0.2 + beverage.cost();
}
}
Test:
publicclass test {
publicstaticvoid main(String[] args) {
//加两份摩卡
Beverage beverage = new Mocha(new Mocha(new Espresso()));
//
System.out.println(beverage.cost());
}
}
里面最重要的核心是:
1. 咖啡类和装饰类都继承饮料类,有同样的cost()方法。
2. 装饰类里面有一个饮料类的变量,用来存放咖啡类,或是经过装饰的咖啡类。
真实世界的装饰者:javaI/O
FileInputStream
BufferedInputStream
LineNumberInputStream
new LineNumberInputStream(new BufferedInputStream(newFileInputStream("a.txt")))
装饰者模式:动态地将责任附加到对象上。想要扩展功能,装饰者提供有别于继承另一种选择。