结构设计模式:装饰器模式

以前,我们使用模式更改了抽象对象的行为,并使用复合模式并委托了请求,从而为组件实现了类似树的结构。

装饰器模式允许将行为静态或动态地添加到单个对象,而不会影响同一类中其他对象的行为。

因此,请设想对我们的一种产品应用各种折扣的情况。

我们将从打折界面开始,指定打折动作。

package com.gkatzioura.design.structural.decorator;

import java.math.BigDecimal;

public interface Discount {
    
    BigDecimal apply(BigDecimal originalPrice);
    
}

实施折价的对象将应用折价并返还折价。
我们要应用的折扣之一是针对新注册会员的特殊折扣。
新注册的会员首次下单可享受20%的折扣

package com.gkatzioura.design.structural.decorator;

import java.math.BigDecimal;

public class NewlyRegisteredDiscount implements Discount {

    public static final BigDecimal SEVENTY_FIVE = new BigDecimal(75);
    public static final BigDecimal ONE_HUNDRED = new BigDecimal(100);

    @Override
    public BigDecimal apply(BigDecimal originalPrice) {

        return originalPrice.multiply(SEVENTY_FIVE).divide(ONE_HUNDRED);
    }

}

如您所见,有时会应用多个折扣。
我们的系统还为我们的客户提供5美元的优惠券折扣。

应用多次折扣非常常见,我们的系统必须支持此操作。 创建打折的包裹是很常见的,实际上这只是包裹的组合。
为此,我们将利用装饰器模式。
我们将创建折扣装饰器。

package com.gkatzioura.design.structural.decorator;

import java.math.BigDecimal;

public class DiscountDecorator implements Discount {

    protected Discount discount;

    public DiscountDecorator(Discount discount) {
        this.discount = discount;
    }

    @Override
    public BigDecimal apply(BigDecimal originalPrice) {
        return discount.apply(originalPrice);
    }
}

因此,我们希望为其他用户引用的新用户提供首次购买折扣和5美元的折扣。
我们将此折扣称为“参考用户”折扣。
目标是要有5美元的折扣,并且对原始价格要有折扣。

package com.gkatzioura.design.structural.decorator;

import java.math.BigDecimal;

public class ReferencedUserDiscount extends DiscountDecorator {

    public static final BigDecimal FIVE = new BigDecimal(5);

    public ReferencedUserDiscount(Discount discount) {
        super(discount);
    }
    
    @Override
    public BigDecimal apply(BigDecimal originalPrice) {

        BigDecimal discountedPrice = super.apply(originalPrice);

        if(discountedPrice.compareTo(FIVE)<=0) {
            return discountedPrice;
        }

        return discountedPrice.subtract(FIVE);
    }
}

现在想象一下忠诚度折扣的情况。 我们希望为我们的用户提供两年计划,每笔订单的折扣为5%。

package com.gkatzioura.design.structural.decorator;

import java.math.BigDecimal;

public class TwoYearPlanDiscount extends DiscountDecorator {

    public static final BigDecimal NINETY_NINE = new BigDecimal(95);
    public static final BigDecimal ONE_HUNDRED = new BigDecimal(100);

    public TwoYearPlanDiscount(Discount discount) {
        super(discount);
    }

    @Override
    public BigDecimal apply(BigDecimal originalPrice) {
        return super.apply(originalPrice).multiply(NINETY_NINE).divide(ONE_HUNDRED);
    }

}

如您所见,在参考用户折扣的情况下和在两年计划折扣的情况下,我们都没有更改新注册用户的原始折扣。 我们所做的是装饰原始折扣并通过考虑各种选择来返还折扣。

装饰器模式是关于

  • 在运行时动态添加责任或将其从对象中动态删除。
  • 无需子类化即可灵活扩展功能

因此,让我们付诸行动。

package com.gkatzioura.design.structural.decorator;

import java.math.BigDecimal;

public class DecoratorScenario {

    public static void main(String args[]) {

        NewlyRegisteredDiscount newlyRegisteredDiscount = new NewlyRegisteredDiscount();
        ReferencedUserDiscount referencedUserDiscount = new ReferencedUserDiscount(newlyRegisteredDiscount);
        TwoYearPlanDiscount twoYearPlanDiscount = new TwoYearPlanDiscount(referencedUserDiscount);
        BigDecimal discountPrice = twoYearPlanDiscount.apply(new BigDecimal(100));
    }

}

我们新注册的用户将享受三种折扣。

您可以在github上找到源代码。

翻译自: https://www.javacodegeeks.com/2018/08/structural-design-decorator-pattern.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值