标签:
早晨有时候会去附近煎饼店买煎饼,煎饼店有卖咸味煎饼、甜味煎饼、无味煎饼。在煎饼制作的过程中,煎饼阿姨会问,"需要添加点什么吗"之类的话,我若选择咸味味煎饼加鸡蛋加火腿的时候,我需要付给阿姨的钱金额=咸味烧饼的钱+鸡蛋的钱+火腿的钱。现有需求:为煎饼店开发一套点餐系统,自动为顾客所点的不同口味且添加了不同添加辅料(鸡蛋、火腿、大葱、熏肉、生菜等)的煎饼算出最终售价。当我们看到如下图所示的那么些类,肯定会很烦恼。
这还仅仅只考虑三种辅料(鸡蛋,火腿,熏肉),当需要考虑大葱,生菜等,类一下子增多了很多很多。很明显,我们不可以采用此种方法。
当我们编写虚类Pancake,代码:
package com.raze.progress; /** * @author DJM * @version 1.0 */ public abstract class Pancake { private String description; private Boolean egg; private Boolean ham; private Boolean pork; public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public Boolean getEgg() { return egg; } public void setEgg(Boolean egg) { this.egg = egg; } public Boolean getHam() { return ham; } public void setHam(Boolean ham) { this.ham = ham; } public Boolean getPork() { return pork; } public void setPork(Boolean pork) { this.pork = pork; } public abstract float cost(); }
这样的弊端也很明显,首先根据开闭原则(Open close principle)的要求,对扩展开放,对修改关闭。这样就已不适用,因为当煎饼店添加了新的辅料,我们不得不修改类Pancake类。另外,当客户点了两个及以上的鸡蛋的时候,这种方法彻底瘫痪了。所以这种方法,也需要舍弃。
我编写了一个虚类Pancake,代码如下:
package com.raze.decorator.component; /** * @author DJM * @version 1.0 */ public abstract class Pancake { private String description; private Float price; public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public Float getPrice() { return price; } public void setPrice(Float price) { this.price = price; } public abstract float cost(); }
并编写三个继承了虚类Pancake的子类,具体代码如下:
package com.raze.decorator.component.concrete; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.raze.decorator.component.Pancake; /** * 无添加煎饼 * @author DJM * @version 1.0 */ public class FanclPancake extends Pancake { private static final Logger logger = LoggerFactory.getLogger(FanclPancake.class); public FanclPancake(){ setDescription("FanclPancake"); setPrice(3.0f); } @Override public float cost() { logger.info("The pancake of {} costs {} yuan.", getDescription(), getPrice()); return getPrice(); } }
package com.raze.decorator.component.concrete; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.raze.decorator.component.Pancake; /** * 咸煎饼 * @author DJM * @version 1.0 */ public class SalinePackage extends Pancake { private static final Logger logger = LoggerFactory.getLogger(SalinePackage.class); public SalinePackage() { setDescription("SalinePackage"); setPrice(4.0f); } @Override public float cost() { logger.info("The pancake of {} costs {} yuan.", getDescription(), getPrice()); return getPrice(); } }
package com.raze.decorator.component.concrete; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.raze.decorator.component.Pancake; /** * 甜煎饼 * @author DJM * @version 1.0 */ public class SugarPancake extends Pancake { private static final Logger logger = LoggerFactory.getLogger(SugarPancake.class); public SugarPancake(){ setDescription("SugarPancake"); setPrice(3.5f); } @Override public float cost() { logger.info("The pancake of {} costs {} yuan.", getDescription(), getPrice()); return getPrice(); } }
定义一个装饰类Decorator,代码:
package com.raze.decorator.decorator; import com.raze.decorator.component.Pancake; /** * 装饰者 * @author DJM * @version 1.0 */ public abstract class Decorator extends Pancake { private Pancake pancake; public Pancake getPancake() { return pancake; } public void setPancake(Pancake pancake) { this.pancake = pancake; } }
并为辅料定义类,所有的类如下图:
选出一个类Vegetable的代码进行展示:
package com.raze.decorator.decorator.concrete; import com.raze.decorator.component.Pancake; import com.raze.decorator.decorator.Decorator; /** * 生菜 * @author DJM * @version 1.0 */ public class Vegetable extends Decorator { public Vegetable(Pancake pancake) { setPancake(pancake); } @Override public float cost() { return super.getPancake().cost()+1.0f; } }
现在进行测试,具体代码如下:
package com.raze.decorator; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.raze.decorator.component.Pancake; import com.raze.decorator.component.concrete.FanclPancake; import com.raze.decorator.decorator.Decorator; import com.raze.decorator.decorator.concrete.Egg; import com.raze.decorator.decorator.concrete.Ham; import com.raze.decorator.decorator.concrete.Pork; import com.raze.decorator.decorator.concrete.Vegetable; public class MyDecoratorTest { private static final Logger logger = LoggerFactory.getLogger(MyDecoratorTest.class); @Test public void decorator(){ Pancake pancake = new FanclPancake(); float myCost = pancake.cost(); logger.info("The pancake costs {} yuan.", myCost); Decorator decorator = new Vegetable(pancake); myCost = decorator.cost(); logger.info("The pancake costs {} yuan.", myCost); decorator = new Egg(pancake); myCost = decorator.cost(); logger.info("The pancake costs {} yuan.", myCost); decorator = new Ham(decorator); myCost = decorator.cost(); logger.info("The pancake costs {} yuan.", myCost); decorator = new Pork(decorator); myCost = decorator.cost(); logger.info("The pancake costs {} yuan.", myCost); decorator = new Pork(decorator); myCost = decorator.cost(); logger.info("The pancake costs {} yuan.", myCost); } }
控制台打印的结果为:
认真思考下图,可装饰者设计模式的思路得到新的梳理:
标签:
原文地址:http://my.oschina.net/dengjianming/blog/509306