Java设计模式:装饰者模式(Decorator Pattern)

编程入门 行业动态 更新时间:2024-10-10 04:19:10

Java设计<a href=https://www.elefans.com/category/jswz/34/1771241.html style=模式:装饰者模式(Decorator Pattern)"/>

Java设计模式:装饰者模式(Decorator Pattern)

装饰者模式,涉及的重要设计原则:类应该对扩展开放,对修改关闭

装饰者模式定义:

装饰者模式动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。

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.0
DarkRoast, Mocha, Mocha, Whip: $ 10.3
HouseBlend, 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

更多推荐

Java设计模式:装饰者模式(Decorator Pattern)

本文发布于:2024-02-26 04:38:04,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1701374.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:模式   Java   Pattern   Decorator

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!