Java设计模式:装饰者模式(Decorator Pattern)
来源:互联网 发布:制作新闻的软件 编辑:程序博客网 时间:2024/05/22 00:46
装饰者模式,涉及的重要设计原则:类应该对扩展开放,对修改关闭。
装饰者模式定义:
装饰者模式动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。
UML类图:
装饰者模式事例:
咖啡店
咖啡种类:
1)深焙咖啡(DarkRoast)
2)家庭混合咖啡(HouseBlend)
3)浓咖啡(Espresso)
4)低咖啡因咖啡(Decaf)
5)其它咖啡。。。
咖啡调料:
1)摩卡(Mocha)
2)牛奶(Milk)
3)豆浆(Soy)
4)奶泡(Whip)
5)其它调料。。。
点单:
要一份加了摩卡和奶泡的深焙咖啡...等等
UML类图
代码实现:
Beverage.java
package com.jing.decorator;/** * 所有饮料的抽象超类 * @author LiuJing * */public abstract class Beverage {/** * 饮料的名字 */String description = "Unknow Beverage";/* * 获取饮料的名字 */public String getDescription(){return description;}/*** * 获取饮料的价格 * @return 返回计算后的总价 */public abstract double cost();}
DarkRoast.java
package com.jing.decorator;import java.text.DecimalFormat;/*** * 深烤咖啡 * @author LiuJing * */public class DarkRoast extends Beverage {/*** * 构造时确定名字 */public DarkRoast(){description = "DarkRoast";}/*** * 价格 */public double cost() {double cost = 10.0;// 用于保存2位小数DecimalFormat df = new DecimalFormat("#.00");return Double.valueOf(df.format(cost));}}
Decaf.java
package com.jing.decorator;import java.text.DecimalFormat;/*** * 低咖啡因咖啡 * @author LiuJing * */public class Decaf extends Beverage {/*** * 构造时确定名字 */public Decaf() {description = "Decaf";}/*** * 价格 */public double cost() {double cost = 11.0;DecimalFormat df = new DecimalFormat("#.00");return Double.valueOf(df.format(cost));}}
Espresso.java
package com.jing.decorator;import java.text.DecimalFormat;/*** * 浓咖啡 * @author LiuJing * */public class Espresso extends Beverage {/*** * 构造时确定其名字 */public Espresso(){description = "Espresso";}/*** * 方法返回 该饮料的价格 */public double cost() {double cost = 12.0;DecimalFormat df = new DecimalFormat("#.00");return Double.valueOf(df.format(cost));}}
HouseBlend.java
package com.jing.decorator;import java.text.DecimalFormat;/*** * 家庭混合咖啡 * @author LiuJing * */public class HouseBlend extends Beverage {/*** * 构造时确定其名字 */public HouseBlend(){description = "HouseBlend";}/*** * 返回该咖啡的价格 */public double cost() {double cost = 13.0;DecimalFormat df = new DecimalFormat("#.00");return Double.valueOf(df.format(cost));}}CondimentDecorator.java
package com.jing.decorator;/*** * 调料装饰者抽象超类,继承至 Beverage,便于类型的统一,能彼此替换。 * @author LiuJing * */public abstract class CondimentDecorator extends Beverage {/*** * 用于保存要装饰的咖啡对象 */Beverage beverage;/*** * 所有子类都必须重新实现 getDescription()方法 */public abstract String getDescription();}Milk.java
package com.jing.decorator;import java.text.DecimalFormat;/*** * 咖啡调料 牛奶 Milk >> CondimentDecorator >> Beverage * @author LiuJing * */public class Milk extends CondimentDecorator {/** * 构造时确定要加给谁 * @param beverage */public Milk(Beverage beverage){this.beverage = beverage;}/*** * 不仅显示当前名,还说明被装饰的名字 */@Overridepublic String getDescription() {// TODO Auto-generated method stubreturn beverage.getDescription() + ", Milk";}/*** * 获取本身的价格和咖啡的价格 */@Overridepublic double cost() {// TODO Auto-generated method stubdouble cost = beverage.cost();cost += 0.1;DecimalFormat df = new DecimalFormat("#.00");return Double.valueOf(df.format(cost));}}
Mocha.java
package com.jing.decorator;import java.text.DecimalFormat;/*** * 咖啡调料 摩卡 Mocha >> CondimentDecorator >> Beverage * * @author LiuJing * */public class Mocha extends CondimentDecorator {/** * 构造时确定要加给谁 * * @param beverage */public Mocha(Beverage beverage) {this.beverage = beverage;}/*** * 不仅显示当前名,还说明被装饰的名字 */@Overridepublic String getDescription() {// TODO Auto-generated method stubreturn beverage.getDescription() + ", Mocha";}/*** * 获取本身的价格和咖啡的价格 */@Overridepublic double cost() {// TODO Auto-generated method stubdouble cost = beverage.cost();cost += 0.1;DecimalFormat df = new DecimalFormat("#.00");return Double.valueOf(df.format(cost));}}Soy.java
package com.jing.decorator;import java.text.DecimalFormat;/*** * 咖啡调料 豆浆 Soy >> CondimentDecorator >> Beverage * * @author LiuJing * */public class Soy extends CondimentDecorator {/** * 构造时确定要加给谁 * * @param beverage */public Soy(Beverage beverage) {this.beverage = beverage;}/*** * 不仅显示当前名,还说明被装饰的名字 */@Overridepublic String getDescription() {// TODO Auto-generated method stubreturn beverage.getDescription() + ", Soy";}/*** * 获取本身的价格和咖啡的价格 */@Overridepublic double cost() {// TODO Auto-generated method stubdouble cost = beverage.cost();cost += 0.1;DecimalFormat df = new DecimalFormat("#.00");return Double.valueOf(df.format(cost));}}Whip.java
package com.jing.decorator;import java.text.DecimalFormat;/*** * 咖啡调料 奶泡 Whip >> CondimentDecorator >> Beverage * * @author LiuJing * */public class Whip extends CondimentDecorator {/** * 构造时确定要加给谁 * * @param beverage */public Whip(Beverage beverage) {this.beverage = beverage;}/*** * 不仅显示当前名,还说明被装饰的名字 */@Overridepublic String getDescription() {// TODO Auto-generated method stubreturn beverage.getDescription() + ", Whip";}/*** * 获取本身的价格和咖啡的价格 */@Overridepublic double cost() {// TODO Auto-generated method stubdouble cost = beverage.cost();cost += 0.1;DecimalFormat df = new DecimalFormat("#.00");return Double.valueOf(df.format(cost));}}测试类
Test.java
package com.jing.decorator;public class Test {/** * @param args */public static void main(String[] args) {// TODO Auto-generated method stub// 点了一份浓咖啡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: $ 12.0DarkRoast, Mocha, Mocha, Whip: $ 10.3HouseBlend, Soy, Mocha, Whip: $ 13.3
扩展:
现在咖啡要有区分 大,中,小杯的价格;
同理,
调料因为杯的大小也要区分不同的价格;
Beverage.java
package com.jing.decorator.size;/** * 所有饮料的抽象超类 * @author LiuJing * */public abstract class Beverage {/** * 杯子的容量类型 */public final static int TALL = 1;public final static int GRANDE = 2;public final static int VENTI = 3;/** * 杯子的容量 */private int volume = 2; // 默认为中杯public int getSize() {return volume;}public void setSize(int valume) {this.volume = valume;}public String getSizeDescription() {String type = "未知杯的大小 ";switch(volume){case TALL:type = "小杯";break;case GRANDE:type = "中杯";break;case VENTI:type = "大杯";break;}return type;}/** * 饮料的名字 */String description = "Unknow Beverage";/* * 获取饮料的名字 */public String getDescription(){return description;}/*** * 获取饮料的价格 * @return 返回计算后的总价 */public abstract double cost();}
DarkRoast.java
package com.jing.decorator.size;import java.text.DecimalFormat;/*** * 深烤咖啡 * @author LiuJing * */public class DarkRoast extends Beverage {/*** * 构造时确定名字 */public DarkRoast(){description = "DarkRoast";}public DarkRoast(int volume){setSize(volume);description = "DarkRoast";}/*** * 价格 */public double cost() {double cost = 0.0;if (getSize() == Beverage.TALL) {cost = 10.0;}else if (getSize() == Beverage.GRANDE){cost = 15.0;}else if (getSize() == Beverage.VENTI){cost = 20.0;}DecimalFormat df = new DecimalFormat("#.00");return Double.valueOf(df.format(cost));}}Decaf.java
package com.jing.decorator.size;import java.text.DecimalFormat;/*** * 低咖啡因咖啡 * @author LiuJing * */public class Decaf extends Beverage {/*** * 构造时确定名字 */public Decaf() {description = "Decaf";}public Decaf(int volume){setSize(volume);description = "Decaf";}/*** * 价格 */public double cost() {double cost = 0.0;if (getSize() == Beverage.TALL) {cost = 11.0;}else if (getSize() == Beverage.GRANDE){cost = 16.0;}else if (getSize() == Beverage.VENTI){cost = 21.0;}DecimalFormat df = new DecimalFormat("#.00");return Double.valueOf(df.format(cost));}}Espresso.java
package com.jing.decorator.size;import java.text.DecimalFormat;/*** * 浓咖啡 * @author LiuJing * */public class Espresso extends Beverage {/*** * 构造时确定其名字 */public Espresso(){description = "Espresso";}public Espresso(int volume){setSize(volume);description = "Espresso";}/*** * 方法返回 该饮料的价格 */public double cost() {double cost = 0.0;if (getSize() == Beverage.TALL) {cost = 12.0;}else if (getSize() == Beverage.GRANDE){cost = 17.0;}else if (getSize() == Beverage.VENTI){cost = 22.0;}DecimalFormat df = new DecimalFormat("#.00");return Double.valueOf(df.format(cost));}}
HouseBlend.java
package com.jing.decorator.size;import java.text.DecimalFormat;/*** * 家庭混合咖啡 * @author LiuJing * */public class HouseBlend extends Beverage {/*** * 构造时确定其名字 */public HouseBlend(){description = "HouseBlend";}public HouseBlend(int volume){setSize(volume);description = "HouseBlend";}/*** * 返回该咖啡的价格 */public double cost() {double cost = 0.0;if (getSize() == Beverage.TALL) {cost = 13.0;}else if (getSize() == Beverage.GRANDE){cost = 18.0;}else if (getSize() == Beverage.VENTI){cost = 23.0;}DecimalFormat df = new DecimalFormat("#.00");return Double.valueOf(df.format(cost));}}
CondimentDecorator.java
package com.jing.decorator.size;/*** * 调料装饰者抽象超类,继承至 Beverage,便于类型的统一,能彼此替换。 * @author LiuJing * */public abstract class CondimentDecorator extends Beverage {/*** * 要装饰的咖啡对象 */Beverage beverage;/*** * 所有子类都必须重新实现 getDescription()方法 */public abstract String getDescription();}
Milk.java
package com.jing.decorator.size;import java.text.DecimalFormat;/*** * 咖啡调料 牛奶 Milk >> CondimentDecorator >> Beverage * @author LiuJing * */public class Milk extends CondimentDecorator {/** * 构造时确定要加给谁 * @param beverage */public Milk(Beverage beverage){this.beverage = beverage;setSize(beverage.getSize());}public int getSize(){return beverage.getSize();}/*** * 不仅显示当前名,还说明被装饰的名字 */@Overridepublic String getDescription() {// TODO Auto-generated method stubreturn beverage.getDescription() + ", Milk";}/*** * 获取本身的价格和咖啡的价格 */@Overridepublic double cost() {// TODO Auto-generated method stubdouble cost = beverage.cost();if (getSize() == Beverage.TALL){cost += 0.1;} else if (getSize() == Beverage.GRANDE){cost += 0.2;} else if (getSize() == Beverage.VENTI){cost += 0.3;}DecimalFormat df = new DecimalFormat("#.00");return Double.valueOf(df.format(cost));}}Mocha.java
package com.jing.decorator.size;import java.text.DecimalFormat;/*** * 咖啡调料 摩卡 Mocha >> CondimentDecorator >> Beverage * @author LiuJing * */public class Mocha extends CondimentDecorator {/** * 构造时确定要加给谁 * @param beverage */public Mocha(Beverage beverage){this.beverage = beverage;setSize(beverage.getSize());}public int getSize(){return beverage.getSize();}/*** * 不仅显示当前名,还说明被装饰的名字 */@Overridepublic String getDescription() {// TODO Auto-generated method stubreturn beverage.getDescription() + ", Mocha";}/*** * 获取本身的价格和咖啡的价格 */@Overridepublic double cost() {// TODO Auto-generated method stubdouble cost = beverage.cost();if (getSize() == Beverage.TALL){cost += 0.1;} else if (getSize() == Beverage.GRANDE){cost += 0.2;} else if (getSize() == Beverage.VENTI){cost += 0.3;}DecimalFormat df = new DecimalFormat("#.00");return Double.valueOf(df.format(cost));}}
Soy.java
package com.jing.decorator.size;import java.text.DecimalFormat;/*** * 咖啡调料 豆浆 Soy >> CondimentDecorator >> Beverage * @author LiuJing * */public class Soy extends CondimentDecorator {/** * 构造时确定要加给谁 * @param beverage */public Soy(Beverage beverage){this.beverage = beverage;setSize(beverage.getSize());}public int getSize(){return beverage.getSize();}/*** * 不仅显示当前名,还说明被装饰的名字 */@Overridepublic String getDescription() {// TODO Auto-generated method stubreturn beverage.getDescription() + ", Soy";}/*** * 获取本身的价格和咖啡的价格 */@Overridepublic double cost() {// TODO Auto-generated method stubdouble cost = beverage.cost();if (getSize() == Beverage.TALL){cost += 0.1;} else if (getSize() == Beverage.GRANDE){cost += 0.2;} else if (getSize() == Beverage.VENTI){cost += 0.3;}DecimalFormat df = new DecimalFormat("#.00");return Double.valueOf(df.format(cost));}}Whip.java
package com.jing.decorator.size;import java.text.DecimalFormat;/*** * 咖啡调料 奶泡 Whip >> CondimentDecorator >> Beverage * @author LiuJing * */public class Whip extends CondimentDecorator {/** * 构造时确定要加给谁 * @param beverage */public Whip(Beverage beverage){this.beverage = beverage;setSize(beverage.getSize());}public int getSize(){return beverage.getSize();}/*** * 不仅显示当前名,还说明被装饰的名字 */@Overridepublic String getDescription() {// TODO Auto-generated method stubreturn beverage.getDescription() + ", Whip";}/*** * 获取本身的价格和咖啡的价格 */@Overridepublic double cost() {// TODO Auto-generated method stubdouble cost = beverage.cost();if (getSize() == Beverage.TALL){cost += 0.1;} else if (getSize() == Beverage.GRANDE){cost += 0.2;} else if (getSize() == Beverage.VENTI){cost += 0.3;}DecimalFormat df = new DecimalFormat("#.00");return Double.valueOf(df.format(cost));}}Test.java
package com.jing.decorator.size;public class Test {/** * @param args */public static void main(String[] args) {// TODO Auto-generated method stub// 点了一份浓咖啡Beverage beverage = new Espresso(); // 使用默认中杯System.out.println(beverage.getSizeDescription()+ beverage.getDescription() + ": $ " + beverage.cost());// 点了一份深烤Beverage beverage2 = new DarkRoast();// 默认为中号beverage2.setSize(Beverage.TALL); // 重新设置杯号为小号beverage2 = new Mocha(beverage2); // 加 摩卡装饰beverage2 = new Mocha(beverage2); // 再加 摩卡装饰beverage2 = new Whip(beverage2); // 再加 奶泡装饰System.out.println(beverage2.getSizeDescription()+ beverage2.getDescription() + ": $ " + beverage2.cost());// 点了一份家庭混合Beverage beverage3 = new HouseBlend(Beverage.VENTI); // 构造初始时就设为大号beverage3 = new Soy(beverage3); // 加 豆浆装饰beverage3 = new Mocha(beverage3); // 再加 摩卡装饰beverage3 = new Whip(beverage3); // 再加 奶泡装饰System.out.println(beverage3.getSizeDescription()+ beverage3.getDescription()+ ": $ " + beverage3.cost());// 用 工厂模式 和 生成器模式,可以更好的建立被 装饰者对象}}
输出:
中杯Espresso: $ 17.0小杯DarkRoast, Mocha, Mocha, Whip: $ 10.3大杯HouseBlend, Soy, Mocha, Whip: $ 23.9
阅读全文
1 0
- Java设计模式-装饰者模式(Decorator Pattern)
- Java设计模式:装饰者模式(Decorator Pattern)
- 设计模式-装饰者模式(Decorator Pattern)
- 设计模式-装饰模式(Decorator Pattern)
- Java设计模式之装饰者模式(Decorator pattern)
- Java设计模式--装饰者模式【Decorator Pattern】
- 浅谈 java 设计模式--装饰模式(Decorator pattern)
- Java设计模式——装饰模式(Decorator Pattern)
- 设计模式笔记之装饰者模式(Decorator Pattern)
- 设计模式笔记3:装饰者模式(Decorator Pattern)
- C#设计模式之装饰者模式(Decorator Pattern)
- 设计模式学习(五) -- 装饰者模式 Decorator Pattern
- 设计模式系列(三)装饰者模式(Decorator Pattern)
- 设计模式总结之Decorator Pattern(装饰者模式)
- 设计模式学习总结:装饰者模式(Decorator Pattern)
- 装饰者设计模式(Decorator Pattern)
- 装饰设计模式(decorator design pattern)
- Java设计模式——装饰者模式(Decorator Pattern)
- android 同步服务端的时间
- caffe:最优化方法
- angularjs中的$sompile服务
- 万维链的应用场景(一)
- Mysql备份以及定期清理备份
- Java设计模式:装饰者模式(Decorator Pattern)
- Oracle用户锁定时的解决办法
- hive udf 批量写入redis
- 开发ionic2+cordova环境的搭建
- 作为一个菜鸟的反思
- FCC学习笔记-(五) Basic Algorithm Scripting
- 使用TabHost添加不同tab界面不同的菜单(包含ActionBar)
- .NET CORE 自定义特性的简单操作
- HDU-2017 多校训练赛4-1003-Counting Divisors