装饰者模式主要用来扩展功能的,不会改变原来对象的功能,只做扩展
版本一:
代码如下:
public abstract class BeefNoodle { protected abstract String getMsg(); protected abstract int getPrice(); }
public class BaseBeefNoodle extends BeefNoodle { protected String getMsg(){ return "牛肉面"; } public int getPrice(){ return 5; } }
public class EggDecorator extends BeefNoodle { private BeefNoodle beefNoodle; public EggDecorator(BeefNoodle beefNoodle) { this.beefNoodle = beefNoodle; } //增强的功能(基于真实对象上) protected String getMsg() { return beefNoodle.getMsg() + "+1个鸡蛋"; } //增强的功能(基于真实对象上) protected int getPrice() { return beefNoodle.getPrice() + 1; } }
private BeefNoodle beefNoodle; public SausageDecorator(BeefNoodle beefNoodle) { this.beefNoodle = beefNoodle; } protected String getMsg() { return beefNoodle.getMsg() + "+1根香肠"; } protected int getPrice() { return beefNoodle.getPrice() + 2; }
测试代码:
public class MyTest { public static void main(String[] args) { BeefNoodle beefNoodle; //买一碗牛肉 beefNoodle = new BaseBeefNoodle(); //加一个鸡蛋 beefNoodle = new EggDecorator(beefNoodle); //加根香肠 beefNoodle = new SausageDecorator(beefNoodle); System.out.println(beefNoodle.getMsg()+"总价:"+beefNoodle.getPrice()); } }
效果如下:
版本二:
①根据策略模式获取对应的策略对象
②计算价格用具体的某一个装饰者对象去计算,因为会需要面的基本信息,所以作为构造参数传进来(代表这个对象是被增强的目标),此外各个装饰者对象还扩展了自己的功能,比如 混合了鸡蛋和香肠的类,方法就有三个参数(代表碗数量,鸡蛋数量,烤肠数量)
类图:
代码如下:
public abstract class BeefNoodle { protected abstract String getMsg(Integer amount); protected abstract int getPrice(Integer amount); }
public class BaseBeefNoodle extends BeefNoodle { //amount 牛肉面数量 protected String getMsg(Integer amount){ return "牛肉面 * "+String.valueOf(amount); } //amount 牛肉面数量 public int getPrice(Integer amount){ return 5*amount; } }
public class EggDecorator extends BeefNoodle { private BeefNoodle beefNoodle; public EggDecorator(BeefNoodle beefNoodle) { this.beefNoodle = beefNoodle; } protected String getMsg(Integer eggs) { return beefNoodle.getMsg(1) + "加"+String.valueOf(eggs)+"个鸡蛋"; } protected int getPrice(Integer eggs) { return beefNoodle.getPrice(1) + 1*eggs; } protected String getMsg(Integer noodles,Integer eggs) { return beefNoodle.getMsg(noodles) + "加"+String.valueOf(eggs)+"个鸡蛋"; } protected int getPrice(Integer noodles ,Integer eggs) { return beefNoodle.getPrice(noodles) + 1*eggs; } }
public class SausageDecorator extends BeefNoodle { private BeefNoodle beefNoodle; public SausageDecorator(BeefNoodle beefNoodle) { this.beefNoodle = beefNoodle; } protected String getMsg(Integer sausages) { return beefNoodle.getMsg(1) + "加"+String.valueOf(sausages)+"根香肠"; } protected int getPrice(Integer sausages) { return beefNoodle.getPrice(1) + 2*sausages; } protected String getMsg(Integer noodles ,Integer sausages) { return beefNoodle.getMsg(sausages) + "加"+String.valueOf(sausages)+"根香肠"; } protected int getPrice(Integer noodles ,Integer sausages) { return beefNoodle.getPrice(noodles) + 1*sausages; } }
public class EggsAndSausageDecorator extends BeefNoodle { private BeefNoodle beefNoodle; public EggsAndSausageDecorator(BeefNoodle beefNoodle) { this.beefNoodle = beefNoodle; } protected String getMsg(Integer sausages) { //return beefNoodle.getMsg(1) + "加"+String.valueOf(sausages)+"根香肠"; return ""; } protected int getPrice(Integer sausages) { //return beefNoodle.getPrice(1) + 2*sausages; return 0; } protected String getMsg(Integer noodles ,Integer eggs,Integer sausages) { return beefNoodle.getMsg(sausages) + "加"+String.valueOf(eggs)+"个鸡蛋"+"加"+String.valueOf(sausages)+"根香肠"; } protected int getPrice(Integer noodles,Integer eggs,Integer sausages) { return beefNoodle.getPrice(noodles) +1*eggs +2*sausages; }
// 策略模式,获得不同的策略对象,具体的计算方式是在各个策略对象(装饰者对象)实现的 public class Strategy { public static final String ONLY_NOODLE = "Noodle"; public static final String WITH_EGGS = "Eggs"; public static final String WITH_SAUSAGES = "Sausages"; public static final String WITH_EGGS_AND_SAUSAGES = "EggsAndSausages"; private static MapnoodleStrategy = new HashMap (); static{ BeefNoodle beefNoodle = new BaseBeefNoodle(); noodleStrategy.put(ONLY_NOODLE,beefNoodle); noodleStrategy.put(WITH_EGGS,new EggDecorator(beefNoodle)); noodleStrategy.put(WITH_SAUSAGES,new SausageDecorator(beefNoodle)); noodleStrategy.put(WITH_EGGS_AND_SAUSAGES,new EggsAndSausageDecorator(beefNoodle)); } public static BeefNoodle get(String noodleKey){ if(!noodleStrategy.containsKey(noodleKey)){ return noodleStrategy.get(ONLY_NOODLE); } return noodleStrategy.get(noodleKey); } } 测试类:
public class MyTest { public static void main(String[] args) { //选择不同的策略 //一碗牛肉面 BeefNoodle onlyBeefNoodle = Strategy.get(Strategy.ONLY_NOODLE); System.out.println("只来一碗牛肉面"+onlyBeefNoodle.getMsg(1)+"价格为:"+ String.valueOf(onlyBeefNoodle.getPrice(1))); //两碗面 System.out.println("只来两碗牛肉面"+onlyBeefNoodle.getMsg(2)+"价格为:"+ String.valueOf(onlyBeefNoodle.getPrice(2))); // 策略模式选择加 鸡蛋的 策略; 要用子类的方法,所以需要强转下 EggDecorator beefNoodleWithEggs = (EggDecorator)Strategy.get(Strategy.WITH_EGGS); System.out.println("只来一碗牛肉面加一个鸡蛋 "+beefNoodleWithEggs.getMsg(1,1)+"价格为:"+ String.valueOf(beefNoodleWithEggs.getPrice(1,1))); System.out.println("只来一碗牛肉面加两个鸡蛋 "+beefNoodleWithEggs.getMsg(1,2)+"价格为:"+ String.valueOf(beefNoodleWithEggs.getPrice(1,2))); System.out.println("只来两碗碗牛肉面加两个鸡蛋 "+beefNoodleWithEggs.getMsg(2,2)+"价格为:"+ String.valueOf(beefNoodleWithEggs.getPrice(2,2))); // 策略模式选择加 香肠的 策略; 要用子类的方法,所以需要强转下 SausageDecorator beefNoodleWithSausage = (SausageDecorator)Strategy.get(Strategy.WITH_SAUSAGES); System.out.println("只来一碗牛肉面加一个香肠 "+beefNoodleWithSausage.getMsg(1,1)+"价格为:"+ String.valueOf(beefNoodleWithSausage.getPrice(1,1))); System.out.println("只来一碗牛肉面加两个香肠 "+beefNoodleWithSausage.getMsg(1,2)+"价格为:"+ String.valueOf(beefNoodleWithSausage.getPrice(1,2))); System.out.println("只来两碗碗牛肉面共加两个香肠 "+beefNoodleWithSausage.getMsg(2,2)+"价格为:"+ String.valueOf(beefNoodleWithSausage.getPrice(2,2))); //策略模式选择加 鸡蛋和香肠 EggsAndSausageDecorator beefNoodleWithEggsAndSausages = (EggsAndSausageDecorator)Strategy.get(Strategy.WITH_EGGS_AND_SAUSAGES); System.out.println("只来一碗牛肉面加一个鸡蛋一个香肠 "+beefNoodleWithEggsAndSausages.getMsg(1,1,1)+"价格为:"+ String.valueOf(beefNoodleWithEggsAndSausages.getPrice(1,1,1))); System.out.println("只来一碗牛肉面加两个鸡蛋两个香肠 "+beefNoodleWithEggsAndSausages.getMsg(1,2,2)+"价格为:"+ String.valueOf(beefNoodleWithEggsAndSausages.getPrice(1,4,4))); System.out.println("只来两碗碗牛肉面各加两个鸡蛋两个香肠 "+beefNoodleWithEggsAndSausages.getMsg(2,4,4)+"价格为:"+ String.valueOf(beefNoodleWithEggsAndSausages.getPrice(2,4,4))); } }
测试结果:
只来一碗牛肉面牛肉面 * 1价格为:5
只来两碗牛肉面牛肉面 * 2价格为:10
只来一碗牛肉面加一个鸡蛋 牛肉面 * 1加1个鸡蛋价格为:6
只来一碗牛肉面加两个鸡蛋 牛肉面 * 1加2个鸡蛋价格为:7
只来两碗碗牛肉面加两个鸡蛋 牛肉面 * 2加2个鸡蛋价格为:12
只来一碗牛肉面加一个香肠 牛肉面 * 1加1根香肠价格为:6
只来一碗牛肉面加两个香肠 牛肉面 * 2加2根香肠价格为:7
只来两碗碗牛肉面共加两个香肠 牛肉面 * 2加2根香肠价格为:12
只来一碗牛肉面加一个鸡蛋一个香肠 牛肉面 * 1加1个鸡蛋加1根香肠价格为:8
只来一碗牛肉面加两个鸡蛋两个香肠 牛肉面 * 2加2个鸡蛋加2根香肠价格为:17
只来两碗碗牛肉面各加两个鸡蛋两个香肠 牛肉面 * 4加4个鸡蛋加4根香肠价格为:22