【Java】装饰器模式
2015-11-03 09:39
423 查看
本文主要是介绍《【C++】装饰器模式》(点击打开链接)的Java版。关于什么是装饰器模式就不再赘述了,这次主要说明从UML类图是如何与代码联系起来的。
还是从2012年上半年软件设计师的软考题来说明这个例子。
题目是这样的:某咖啡店当卖咖啡时,可以根据顾客的要求在其中加入各种配料,咖啡店会根据所加入的配料来计算费用。咖啡店所供应的咖啡及配料的种类和价格如下表所示。
咖啡有两种:蒸馏咖啡Espresso 25元/杯,深度烘焙咖啡DarkRoast 20元/杯
可以在咖啡里面加配料:摩卡Mocha 10元/份,奶泡Whip 8元/份
现采用装饰器模式Decorator模式来实现计算费用的功能,得到如图5-1所示的类图。
1、UML中,白色箭头代表继承关系,例如上图Espresso就继承了Beverage,从上述的UML可以看到,Beverage是所有类的父类,然而题目在Beverage类中定义了类成员,也出先有代码体的getDescription(),因此注定Beverage只可能是抽象类abstract而不是接口。而int cost()方法不想在此类给出相应的实现,因此必须定义为抽象方法。
2、CondimentDecorator的分析从下面已经给出的Mocha与Whip入手,因为其子类Mocha与Whip的构造方法出现了CondimentDecorator的父类——Beverage中没有的Beverage beverage,因此其CondimentDecorator必须有一个Beverage beverage;定义,而Beverage中存在的方法与声明,就无须再写了。
3、最后,本题询问主函数的构造函数是如何的。没什么好说的,就是根据类中定义的方法,传入正确的参数。
就可以达到了最终的层层叠加的装饰器模式目的。
具体实现代码如下所示:
abstract class Beverage { // 饮料
String description = "Unknown Beverage";
public String getDescription() {
return description;
}
public abstract int cost();
}
abstract class CondimentDecorator extends Beverage { // 配料
Beverage beverage;
}
class Espresso extends Beverage { // 蒸馏咖啡
private final int ESPRESSO_PRICE = 25;
public Espresso() {
description = "Espresso";
}
public int cost() {
return ESPRESSO_PRICE;
}
}
class DarkRoast extends Beverage { // 深度烘焙咖啡
private final int DARKROAST_PRICE = 20;
public DarkRoast() {
description = "DarkRoast";
}
public int cost() {
return DARKROAST_PRICE;
}
}
class Mocha extends CondimentDecorator { // 摩卡
private final int MOCHA_PRICE = 10;
public Mocha(Beverage beverage) {
this.beverage = beverage;
}
public String getDescription() {
return beverage.getDescription() + ", Mocha";
}
public int cost() {
return MOCHA_PRICE + beverage.cost();
}
}
class Whip extends CondimentDecorator { // 奶泡
private final int WHIP_PRICE = 8;
public Whip(Beverage beverage) {
this.beverage = beverage;
}
public String getDescription() {
return beverage.getDescription() + ", Whip";
}
public int cost() {
return WHIP_PRICE + beverage.cost();
}
}
public class Coffee {
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());
}
}
运行的结果为:
还是从2012年上半年软件设计师的软考题来说明这个例子。
题目是这样的:某咖啡店当卖咖啡时,可以根据顾客的要求在其中加入各种配料,咖啡店会根据所加入的配料来计算费用。咖啡店所供应的咖啡及配料的种类和价格如下表所示。
咖啡有两种:蒸馏咖啡Espresso 25元/杯,深度烘焙咖啡DarkRoast 20元/杯
可以在咖啡里面加配料:摩卡Mocha 10元/份,奶泡Whip 8元/份
现采用装饰器模式Decorator模式来实现计算费用的功能,得到如图5-1所示的类图。
1、UML中,白色箭头代表继承关系,例如上图Espresso就继承了Beverage,从上述的UML可以看到,Beverage是所有类的父类,然而题目在Beverage类中定义了类成员,也出先有代码体的getDescription(),因此注定Beverage只可能是抽象类abstract而不是接口。而int cost()方法不想在此类给出相应的实现,因此必须定义为抽象方法。
2、CondimentDecorator的分析从下面已经给出的Mocha与Whip入手,因为其子类Mocha与Whip的构造方法出现了CondimentDecorator的父类——Beverage中没有的Beverage beverage,因此其CondimentDecorator必须有一个Beverage beverage;定义,而Beverage中存在的方法与声明,就无须再写了。
3、最后,本题询问主函数的构造函数是如何的。没什么好说的,就是根据类中定义的方法,传入正确的参数。
就可以达到了最终的层层叠加的装饰器模式目的。
具体实现代码如下所示:
abstract class Beverage { // 饮料
String description = "Unknown Beverage";
public String getDescription() {
return description;
}
public abstract int cost();
}
abstract class CondimentDecorator extends Beverage { // 配料
Beverage beverage;
}
class Espresso extends Beverage { // 蒸馏咖啡
private final int ESPRESSO_PRICE = 25;
public Espresso() {
description = "Espresso";
}
public int cost() {
return ESPRESSO_PRICE;
}
}
class DarkRoast extends Beverage { // 深度烘焙咖啡
private final int DARKROAST_PRICE = 20;
public DarkRoast() {
description = "DarkRoast";
}
public int cost() {
return DARKROAST_PRICE;
}
}
class Mocha extends CondimentDecorator { // 摩卡
private final int MOCHA_PRICE = 10;
public Mocha(Beverage beverage) {
this.beverage = beverage;
}
public String getDescription() {
return beverage.getDescription() + ", Mocha";
}
public int cost() {
return MOCHA_PRICE + beverage.cost();
}
}
class Whip extends CondimentDecorator { // 奶泡
private final int WHIP_PRICE = 8;
public Whip(Beverage beverage) {
this.beverage = beverage;
}
public String getDescription() {
return beverage.getDescription() + ", Whip";
}
public int cost() {
return WHIP_PRICE + beverage.cost();
}
}
public class Coffee {
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());
}
}
运行的结果为:
相关文章推荐
- struts2 action 页面跳转,有两个跳转类型是亲试过
- Java SE复习笔记64
- 总结1:: springweb项目基本包结构/eclipse编辑器
- Java SE复习笔记63
- jdbcType与javaType的对应关系
- jdbcType与javaType的对应关系
- 详解Java GC的工作原理+Minor GC、FullGC
- SpringMVC小案例搭建
- Java 泛型中? super T和? extends T的区别
- 从”JAVA“而终 3 :配置java运行环境以及Myeclipse的安装
- Java 并发包中的读写锁及其实现分析
- Spring中的Resource接口
- Java SE复习笔记62
- spring和springmvc的配置文件写法
- 九种基本数据类型
- java检测某个类所在的包名路径
- java SE复习笔记61
- JUnit-4.11使用报java.lang.NoClassDefFoundError: org/hamcrest/SelfDescribing错误
- 反射在Java中的应用
- MyEclipse 清理项目缓存的几大方法