java与模式孙悟空_由孙悟空的七十二变看Java设计模式:装饰者模式

应用场景

京东、天猫双十一,情人节商品大促销,各种商品有不同的促销活动

满减:满200减50

每满减:每满100减10

打折:买两件8折,三件7折

数量减:满三件减去最低价的一件

假设现在顾客买了两件衣服先是打了8折,然后又满200减了50,促销活动多重叠加了,该如何灵活实现订单金额计算?

代码示例

PromotionAlgorithm接口,计算订单金额:

public interface PromotionAlgorithm{

Order promotionAlgorithm(Order order);

}

复制代码

实现类PromotionAlgorithm1、PromotionAlgorithm2:

public class PromotionAlgorithm1 implements PromotionAlgorithm{

@Override

public Order promotionAlgorithm(Order order){

System.out.println("打8折");

order.setPrice(order.getPrice() * 0.8);

return order;

}

}

复制代码

public class PromotionAlgorithm2 implements PromotionAlgorithm{

@Override

public Order promotionAlgorithm(Order order){

System.out.println("满200减了50");

order.setPrice(order.getPrice() - 50);

return order;

}

}

复制代码

OrderService类:

public class OrderService{

public Order getOrderPrices(Order order, String... promotion){

for (String s : promotion) {

if (s.equals("promotion-1")) {

new PromotionAlgorithm1().promotionAlgorithm(order);

} else if (s.equals("promotion-2")) {

new PromotionAlgorithm2().promotionAlgorithm(order);

}

}

return order;

}

}

复制代码

测试类:

public class Test{

public static void main(String[] args){

OrderService service = new OrderService();

Order order = new Order();

order.setPrice(1000.0);

String[] array = {"promotion-1", "promotion-2"};

Order result = service.getOrderPrices(order, array);

System.out.println("最终我花了:" + result.getPrice());

}

}

复制代码

4abd4aa4eedce9df2bb86da71b982a07.png

现在思考一下,当需要对一个类的多个方法进行增强时,使用者会随意使用被增强方法时,上面的for循环还灵活吗

改进代码

定义一个接口OrderComponent:

public interface OrderComponent{

/** 促销方式 */

String getPromotion();

/** 价格 */

Double getPrice();

}

复制代码

OrderConcreteComponent类:需要进行计算的类

public class OrderConcreteComponent implements OrderComponent{

@Override

public String getPromotion(){

return "我买了三件衣服,衣服总共1000元,";

}

@Override

public Double getPrice(){

return 1000.0;

}

}

复制代码

OrderDecorator类:有一个属性,是上面的接口OrderComponent,实现了OrderComponent接口

public class OrderDecorator implements OrderComponent{

public OrderComponent component;

public OrderDecorator(OrderComponent component){

this.component = component;

}

@Override

public String getPromotion(){

return this.component.getPromotion();

}

@Override

public Double getPrice(){

return this.component.getPrice();

}

}

复制代码

OrderDecoratorA类:打折类

public class OrderDecoratorA extends OrderDecorator{

public OrderDecoratorA(OrderComponent component){

super(component);

}

@Override

public String getPromotion(){

return this.component.getPromotion() + "衣服打了8折,";

}

@Override

public Double getPrice(){

return this.component.getPrice() * 0.8;

}

}

复制代码

OrderDecoratorB类:满减类

public class OrderDecoratorB extends OrderDecorator{

public OrderDecoratorB(OrderComponent component){

super(component);

}

@Override

public String getPromotion(){

return this.component.getPromotion() + "又满200减了50。";

}

@Override

public Double getPrice(){

return this.component.getPrice() - 50;

}

}

复制代码

测试类:

public class Test{

public static void main(String[] args){

OrderComponent component = new OrderConcreteComponent();

OrderComponent c = new OrderDecorator(component);

OrderComponent d = new OrderDecoratorA(c);

OrderComponent e = new OrderDecoratorB(d);

System.out.println(e.getPromotion());

System.out.println("最终我花了:" + e.getPrice());

}

}

复制代码

8b41c0cc88cb3a55fd7c26f5df48ec27.png

上面的改进代码,就是装饰者模式的基本运用

装饰者模式

定义

以装饰的方式,动态地将责任附加到对象上,同时又不改变其结构

意图

动态地给一个对象添加一些额外的职责。就增加功能来说,装饰者模式相比生成子类更为灵活

主要解决问题

一般的,我们为了扩展一个类经常使用继承方式实现,由于继承为类引入静态特征,并且随着扩展功能的增多,子类会很膨胀

何时使用

在不想增加很多子类的情况下扩展类

优缺点

优点:

不改变具体类代码,动态叠加增强行为功能

若要扩展功能,装饰者提供了比继承更有弹性的替代方案

装饰类和被装饰类可以独立发展,不会相互耦合

缺点:

多层装饰比较复杂

类图:

51268f5efaa890fe07e997a3ad09c2ac.png

涉及到的角色:

抽象构建(Component)角色:给出一个抽象接口,来规范准备接收附加责任的对象

具体构建(ConcreteComponent)角色:定义一个将要接收附加责任的类,即被装饰者

装饰(Decorator)角色:持有一个构建(Component)对象的实例,并定义一个与抽象接口一致的接口

具体装饰(ConcreteDecorator)角色:即上图中的DecoratorA、DecoratorB,负责给构建对象贴上附加的责任,即具体的功能增强行为在这个角色里面

Component类:

public interface Component{

void sampleOperation();

}

复制代码

ConcreteComponent类:

public class ConcreteComponent implements Component{

@Override

public void sampleOperation(){

//do something

}

}

复制代码

Decorator类:

public class Decorator implements Component{

private Component component;

public Decorator(Component component){

this.component = component;

}

@Override

public void sampleOperation(){

this.component.sampleOperation();

}

}

复制代码

ConcreteDecorator类:

public class ConcreteDecorator extends Decorator{

public ConcreteDecorator(Component component){

super(component);

}

@Override

public void sampleOperation(){

super.sampleOperation();

}

}

复制代码

装饰者模式常常也被称为包裹模式,就是因为每一个具体的装饰类都将下一个具体装饰类或者具体构建类包裹起来

假设有2个具体装饰类Decorator1、Decorator2,还有一个具体构建类ConcreteComponent:

3ed1d704860cd5957ee90acb4b205515.png

是的没错,就是像套娃一样,一层包裹一层

孙悟空的七十二变

大家都知道,孙悟空有七十二般变化,每一种变化都会给他带来一种附加的本领,变成鱼可以在水中游,变成鸟可以在空中飞,但是无论怎么样的变化,在二郎神眼中,还是一只猴子

6318e08173deadb334faa38f16fcc832.png

齐天大圣类:拥有七十二般变化

public interface MonkeyKing{

/** 七十二变 */

String change();

}

复制代码

大圣本尊类:

public class ConcreteMonkey implements MonkeyKing{

@Override

public String change(){

return "我是齐天大圣本尊!";

}

}

复制代码

大圣化身类:

public class DecoratorMonkeyChange implements MonkeyKing{

public MonkeyKing king;

public DecoratorMonkeyChange(MonkeyKing king){

this.king = king;

}

@Override

public String change(){

return this.king.change();

}

}

复制代码

大圣具体化身类:

public class DecoratorMonkeyChange1 extends DecoratorMonkeyChange{

public DecoratorMonkeyChange1(MonkeyKing king){

super(king);

}

@Override

public String change(){

return this.king.change() + "变成了鱼!";

}

}

复制代码

public class DecoratorMonkeyChange2 extends DecoratorMonkeyChange{

public DecoratorMonkeyChange2(MonkeyKing king){

super(king);

}

@Override

public String change(){

return this.king.change() + "变成了鸟!";

}

}

复制代码

测试类:

public class TestMonkey{

public static void main(String[] args){

MonkeyKing king = new ConcreteMonkey();

MonkeyKing a = new DecoratorMonkeyChange(king);

MonkeyKing b = new DecoratorMonkeyChange1(a);

MonkeyKing c = new DecoratorMonkeyChange2(b);

System.out.println(c.change());

}

}

复制代码

2f8a413090ada2c5a57b46e5f3aace61.png

类图:

32a6cc42e112e76e4725855d54e53a32.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值