一、情景:
老王在卖的煎饼摊子开张了,主营产品有煎饼、鸡蛋、火腿。 问题:1、有顾客想买加了鸡蛋的煎饼、或者加了火腿、鸡蛋的煎饼,那么该如何改造呢?
二、情景后续
设计模式大佬、推荐他用装饰者模式,进行包装、包装出带有鸡蛋的煎饼
三、装饰者模式(Decorator)
定义:动态的将责任附加到对象上若老扩展功能,装饰者提供老比继承更有弹性的替代方案重要组件Component 被包装的原始组件Decorator 实现与原始组件相同的接口,并且组合了一个原始组件的引用
四、代码演示
4.1类图
4.2 煎饼、鸡蛋、火腿公共接口(Component)
public interface JbComponent {
public String
desc();
public BigDecimal
price();
}
4.3 各自的实现(ConcreteComponent)
public class JbComponenteEgg implements JbComponent {
@Override
public String
desc() {
return "鸡蛋";
}
@Override
public BigDecimal
price() {
return new BigDecimal("1");
}
}
public class JbComponentPancakes implements JbComponent{
@Override
public String
desc() {
return "煎饼";
}
@Override
public BigDecimal
price() {
return new BigDecimal(2);
}
}
public class JbComponenthHotDog implements JbComponent {
@Override
public String
desc() {
return "火腿";
}
@Override
public BigDecimal
price() {
return new BigDecimal(1);
}
}
4.4 装饰者——带有鸡蛋煎饼(ConcreteDecoratoerA)
public class DecoratorPancakesWithEgg implements JbComponent {
private JbComponent jbComponent
;
public DecoratorPancakesWithEgg(JbComponent jbComponent
) {
this.jbComponent
= jbComponent
;
}
@Override
public String
desc() {
return jbComponent
.desc() + "\t" + "加鸡蛋";
}
@Override
public BigDecimal
price() {
return jbComponent
.price().add(BigDecimal
.ONE
);
}
}
4.5 装饰者——带有鸡蛋、火腿的煎饼(ConcreteDecoratoerB)
public class DecoratorPancakesWithHotDog implements JbComponent{
private JbComponent jbComponent
;
public DecoratorPancakesWithHotDog(JbComponent jbComponent
) {
this.jbComponent
= jbComponent
;
}
@Override
public String
desc() {
return jbComponent
.desc() +"\t" + "加热狗";
}
@Override
public BigDecimal
price() {
return jbComponent
.price().add(BigDecimal
.ONE
);
}
}
4.6 代码测试
public class DemoMain {
public static void main(String
[] args
) {
JbComponent jbComponent1
= new JbComponenthHotDog();
System
.out
.println("卖" + jbComponent1
.desc() + "\t 价格" +jbComponent1
.price());
JbComponent jbComponent2
= new JbComponenteEgg();
System
.out
.println("卖" + jbComponent2
.desc() + "\t 价格" +jbComponent2
.price());
JbComponent jbComponent3
= new JbComponentPancakes();
System
.out
.println("卖" + jbComponent3
.desc() + "\t 价格" +jbComponent3
.price());
System
.out
.println("==开始卖包装产品==");
JbComponent jbComponent4
= new DecoratorPancakesWithEgg(jbComponent3
);
System
.out
.println("卖" + jbComponent4
.desc() + "\t 价格" +jbComponent4
.price());
JbComponent jbComponent5
= new DecoratorPancakesWithEgg(jbComponent4
);
System
.out
.println("卖" + jbComponent5
.desc() + "\t 价格" +jbComponent5
.price());
}
}
五、小结
5.1改造之后的煎饼摊子
5.2总结
装饰者模式同继承一样,可以扩展行为,这符合开闭原则,但是有一个不好的地方就是这样会到账设计中出现很多小对象,程序的复杂性会增加。装饰者可以不断的叠加,例如上述案例中,可以用完包装完鸡蛋后,继续包装鸡蛋、不断重复包装行为。