装饰者模式:动态地将责任附加到对象上。想要扩展功能,装饰者提供有别于继承的另一种选择。
现在,我们有一个场景,咖啡店出售各种不同的咖啡,而不同的咖啡中可以加入各种不同的调料,根据咖啡种类和加入的调料来计算价格。下面我们就用代码来简单实现下这个场景,也就是装饰者模式,其中咖啡为主体,调料是用来装饰咖啡的,比如想要一杯摩卡和奶泡的深焙咖啡,那么要做的是:
1:拿一个深焙咖啡DarkRoast对象
2:以摩卡Mocha对象来进行装饰
3:以奶泡Whip对象进行装饰
4:调用cost方法,并依赖委托将调料价格加上去。
好了,直接上代码理解装饰者模式吧。
第一步:先创建一个基类,所有咖啡和调料都是扩展自这个类的。这就说明装饰者和被装饰者对象都有相同的超类型。
//基类
public abstract class Coffer {
String descirption = "Unknown Coffer";
public String getDescription(){
return descirption;
}
//所有子类必须实现这个方法来计算价格
public abstract double cost();
}
第二步:创建一个调料的抽象类,也就是装饰者类,具体的装饰者类实现此类。
//抽象的装饰者,调料类,扩展自Coffer
public abstract class Condiment extends Coffer{
public abstract String getDescription();
}
第三步:创建具体的咖啡类。
//具体的咖啡种类——浓缩咖啡类
public class Espresso extends Coffer{
public Espresso(){
descirption = "Espresso";
}
@Override
public double cost() {
return 1.99;
}
}
//具体的咖啡种类——深焙咖啡类
public class DarkRoast extends Coffer{
public DarkRoast(){
descirption = "DarkRoast";
}
@Override
public double cost() {
return 0.88;
}
}
第四步:创建具体的调料类
//具体的装饰者,摩卡调料
public class Mocha extends Condiment {
//用于记录被装饰者,这里是在构造方法中将参数记录到咖啡的实例变量中,你也可以使用get/set方法
Coffer coffer;
public Mocha(Coffer coffer){
this.coffer = coffer;
}
@Override
public String getDescription() {
return coffer.getDescription() + ", Mocha";
}//代码效果参考:http://www.lyjsj.net.cn/wx/art_24021.html
@Override
public double cost() {
return 0.2 + coffer.cost();
}
}
//具体的装饰者,奶泡调料
public class Whip extends Condiment{
Coffer coffer;
public Whip(Coffer coffer){
this.coffer = coffer;
}
@Override
public String getDescription() {
return coffer.getDescription() + ", Whip";
}
@Override
public double cost() {
return 0.15 + coffer.cost();
}
}
//代码效果参考:http://www.lyjsj.net.cn/wz/art_24019.html
第五步:测试public class Test {
public static void main(String【】 args) {
//来一杯Espresso咖啡
Coffer coffer = new Espresso();
System.out.println(coffer.getDescription() + ",价格:" + coffer.cost());
//来一杯深焙咖啡,加入2分摩卡和1分奶泡
Coffer coffer2 = new DarkRoast();
coffer2 = new Mocha(coffer2);
coffer2 = new Mocha(coffer2);
coffer2 = new Whip(coffer2);
System.out.println(coffer2.getDescription() + ",价格:" + coffer2.cost());
}
}
运行结果:
好了,这就是一个简单的装饰者模式了。在Java的API中,你可以发现,有关IO类就是采用装饰者模式的,如:
LineNumberInputStream inputStream = new LineNumberInputStream(new BufferedInputStream(new FileInputStream(fileName)));
顶层类都是InputStream,具体这里不讲解了。
下一节:工厂模式
作者:哀&RT
出处:博客园哀&RT的技术博客--
您的支持是对博主最大的鼓励,感谢您的认真阅读。
本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文//代码效果参考:http://www.lyjsj.net.cn/wz/art_24017.html
连接,否则保留追究法律责任的权利。