装饰者模式(包装模式)
应用场景:老王是卖豆浆的,现在的豆浆品种不断增多,如下图,可以任意搭配,这种情况如果用继承的方式会形成 类爆炸,并且后期扩展也比较麻烦,这时候就可以用到装置者模式。
代码实现:
1.豆浆属于饮品,创建一个饮品的接口,后期可能还会卖果汁之类的其他饮品
package com.zkxtd.test; /** * 饮品 * @Author zhouhe * @Date 2019/10/28 9:59 */ public interface Drink { //抽象组件 //价格 public double money(); //描述 public String desc(); }
2.创建被装饰者,豆浆,实现饮品Drink接口
package com.zkxtd.test; /** * 豆浆 * 豆浆属于饮品,所以要实现 Drink 这个接口 * @Author zhouhe * @Date 2019/10/28 10:02 */ public class Soya implements Drink{ //被装饰者 @Override public double money() { return 5; } @Override public String desc() { return "纯豆浆"; } }
3.创建一个装饰器,它是一个抽象类,实现Drink,返回装饰后的结果
package com.zkxtd.test; /** * 抽象类 * @Author zhouhe * @Date 2019/10/28 10:08 */ public abstract class Decorator implements Drink{ //装饰器 //1.抽象类 //2.实现抽象组件接口 //3.持有抽象接口的引用 //定义私有的饮品接口引用 private Drink drink; public Decorator(Drink drink){ this.drink = drink; } /** * 重写方法,返回装饰后的结果 * @return */ @Override public double money() { return drink.money(); } @Override public String desc() { return drink.desc(); } }
4.具体装饰
红豆
package com.zkxtd.test; /** * 红豆 * @Author zhouhe * @Date 2019/10/28 10:15 */ public class RedBean extends Decorator{ /** * 在使用ReadBean 的时候需要把 drink 传给父类 * @param drink */ public RedBean(Drink drink) { super(drink); } /** * 重写价格 * @return */ @Override public double money() { return super.money()+3.2; } /** * 重写描述 * @return */ @Override public String desc() { return super.desc()+"+红豆"; } }
鸡蛋
package com.zkxtd.test; /** * @Author zhouhe * @Date 2019/10/28 10:20 */ public class Egg extends Decorator { public Egg(Drink drink) { super(drink); } @Override public double money() { return super.money()+3.9; } @Override public String desc() { return super.desc()+"+鸡蛋"; } }
糖
package com.zkxtd.test; /** * 糖 * @Author zhouhe * @Date 2019/10/28 10:21 */ public class Sugar extends Decorator { public Sugar(Drink drink) { super(drink); } @Override public double money() { return super.money()+2.1; } @Override public String desc() { return super.desc()+"+糖"; } }
5.测试类
package com.zkxtd.test; /** * @Author zhouhe * @Date 2019/10/28 10:24 */ public class Test { public static void main(String[] args) { //开始搭配 //1.创建豆浆对象(豆浆属于饮品,我们返回一个饮品) Drink soya = new Soya(); System.out.println(soya.money()); //打印纯豆浆的信息 System.out.println(soya.desc()); //2.往纯豆浆里面加红豆 //把红豆加到豆浆里面,返回的还是饮品 Drink redBeanSoya = new RedBean(soya); System.out.println(redBeanSoya.money()); //打印加红豆的豆浆的信息 System.out.println(redBeanSoya.desc()); //3.向红豆豆浆中加入鸡蛋 //返回的还是饮品 Drink erbs = new Egg(redBeanSoya); System.out.println(erbs.money()); //打印相关信息 System.out.println(erbs.desc()); } }
使用装饰者模式之后,任何的一个具体装饰都可以装饰当前的一个饮品
现在如果需要加入一种新的辅料西瓜,那么只要建一个西瓜类,然后进行搭配就可以了
package com.zkxtd.test; /** * 西瓜 * @Author zhouhe * @Date 2019/10/28 10:37 */ public class Xigua extends Decorator { public Xigua(Drink drink) { super(drink); } @Override public double money() { return super.money()+4.0; } @Override public String desc() { return super.desc()+"+西瓜"; } }
还可以装饰果汁,果汁也属于饮品
package com.zkxtd.test; /** * 果汁 * @Author zhouhe * @Date 2019/10/28 10:43 */ public class Fruit implements Drink{ @Override public double money() { return 6; } @Override public String desc() { return "果汁"; } }
在测试类中开始搭配果汁