设计模式-优惠券-策略模式

策略模式定义与实现

策略模式的定义

​ 首先我们可以先看一下策略模式的定义:

Define a family of algorithms,encapsulate each one,and make them interchangeable.(定义一组算法,将每个算法都封装起来,并且使它们之间可以互换。)

​ 这个定义是非常明确、清晰的,“定义一组算法”,同一个接口的不同实现类是不是三个算法?“将每个算法都封装起来”,封装类Context不就是这个作用吗?**“使它们可以互换”**当然可以互换了,都实现是相同的接口,那当然可以相互转化了。

​ 下面简单的总结一下,就是我们有一个接口(也可以是抽象类),这个接口有不同的实现类,每一个实现类就是一个策略,并且这里还有一个封装类Context,这个封装类里面就是封装了不同的策略,我们对于策略的调用就是通过这个封装类去执行的。

策略模式的通用类图

​ 下面我们再看一下责策略模式定义的通用的类图是什么样子的。

img

​ 策略模式使用的就是面向对象的继承和多态机制,非常容易理解和掌握,我们再来看看策略模式的三个角色:

Context封装角色

​ 它也叫做上下文角色,起承上启下封装作用,屏蔽高层模块对策略、算法的直接访问,封装可能存在的变化。

Strategy抽象策略角色

​ 策略、算法家族的抽象,通常为接口,定义每个策略或算法必须具有的方法和属性。各位看官可能要问了,类图中的AlgorithmInterface是什么意思,嘿嘿,algorithm是“运算法则”的意思,结合起来意思就明白了吧。

ConcreteStrategy具体策略角色

​ 实现抽象策略中的操作,该类含有具体的算法。

策略模式的通用代码

​ 下面我们可以看一下《设计模式之禅》中讲到的通用代码实现:

抽象策略角色(Strategy)

public interface Strategy { 
    //策略模式的运算法则 
    public void doSomething(); 
}

具体策略角色(ConcreteStrategy)

​ 具体策略也是非常普通的一个实现类,只要实现接口中的方法就可以,伪代码实现我们可以参考如下:

// 具体策略1
public class ConcreteStrategy1 implements Strategy { 
    public void doSomething() { 
        System.out.println("具体策略1的运算法则"); 
    } 
}

// 具体策略2
public class ConcreteStrategy2 implements Strategy {
	public void doSomething() { 
        System.out.println("具体策略2的运算法则"); 
    } 
}

封装角色(Context)

​ 策略模式的重点就是封装角色,它是借用了代理模式的思路,这里我们也可以思考一下,它和代理模式有什么差别,差别就是策略模式的封装角色和被封装的策略类不用是同一个接口,如果是同一个接口那就成为了代理模式。

public class Context { 
    // 抽象策略 
    private Strategy strategy = null;
    
    // 构造函数设置具体策略 
    public Context(Strategy _strategy) { 
        this.strategy = _strategy; 
    }
    
    // 封装后的策略方法 
    public void doAnythinig() { 
        this.strategy.doSomething(); 
    } 
}

高层调用(Client)

​ 这里模拟我们调用策略,一般就是直接调用我们的封装角色,实现解耦的特性。

public class Client { 
    public static void main(String[] args) { 
        // 声明一个具体的策略 
        Strategy strategy = new ConcreteStrategy1(); 
        // 声明上下文对象 
        Context context = new Context(strategy); 
        // 执行封装后的方法 
        context.doAnythinig(); 
    } 
}

实战-策略模式实现优惠券

优惠券业务逻辑说明

​ 这里为了方便大家对策略模式的理解,我这里举例的优惠券的场景是非常简单的一种,实际工作中肯定比这个复杂的多,所以请不要介意细节性的东西,只是为了方便我们去结合一些适用的场景去理解策略模式。

​ 下面说一下我们的优惠券业务场景是,我们有一个优惠券活动,这个活动有两种:满减优惠券(满100减10、满200减30、满500减80)、折扣优惠券(8折优惠)两种。

img

策略模式实现优惠券功能流程图

img

​ 这里面由于优惠券活动有两种优惠券类型,一个是满减优惠券,一个是折扣优惠券,所以我这里就设计了一个优惠券策略接口(CouponStrategy)以及两个具体策略(DiscountCoupon和FullMinusCoupon)折扣优惠券和满减优惠券,还有非常关键的角色就是我们的策略封装角色Context,里面的内容主要是用来封装我们的策略对象。

策略模式实现优惠券功能代码实现

​ idea中代码设计的diagram类图如下所示:

img

CouponStrategy.java(优惠券策略接口)

import java.math.BigDecimal;

/**
 * @author gcc
 * @version 1.0
 * @ClassName ActiveStrategy
 * @description 优惠券策略接口
 * @date 2021/9/30 9:20
 */
public interface CouponStrategy {

    /**
     * 优惠券策略
     * @author gcc
     * @date  2021/9/30 9:21
     */
    void doActive(BigDecimal money);
}

DiscountCoupon.java(折扣优惠券具体策略)

import java.math.BigDecimal;
import java.text.DecimalFormat;

/**
 * @author gcc
 * @ClassName DiscountCoupon 折扣优惠券
 * @description 折扣优惠券
 * @date 2021/9/30 9:23
 */
public class DiscountCoupon implements CouponStrategy {

    /**
     * 折扣优惠券
     *
     * @author gcc
     * @date 2021/9/30 9:24
     */
    @Override
    public void doActive(BigDecimal money) {
        // 8折优惠券
        DecimalFormat decimalFormat =new DecimalFormat("#.00");
        System.out.println("折后优惠价:" + decimalFormat.format(money.multiply(new BigDecimal(0.8d))));
    }
}

FullMinusCoupon.java(满减优惠券具体策略)

import java.math.BigDecimal;

/**
 * @author gcc
 * @version 1.0
 * @ClassName FullMinusCoupon
 * @description 满减优惠券
 * @date 2021/9/30 9:34
 */
public class FullMinusCoupon implements CouponStrategy {
    @Override
    public void doActive(BigDecimal money) {
        Double sourceMoney = money.doubleValue();
        if (sourceMoney < 100) {
            // 不满减
            System.out.println("没有满减 原价:" + sourceMoney);
        } else if (sourceMoney < 200) {
            // 满100减10
            System.out.println("满100减10 优惠后:" + (sourceMoney - 10));
        } else if (sourceMoney < 500) {
            // 满200减30
            System.out.println("满200减30 优惠后:" + (sourceMoney - 30));
        } else {
            // 满500减80
            System.out.println("满500减80 优惠后:" + (sourceMoney - 80));
        }
    }
}

CouponContext.java(优惠券封装角色)

import java.math.BigDecimal;

/**
 * @author gcc
 * @version 1.0
 * @ClassName CouponContext
 * @description 优惠券转换角色Context
 * @date 2021/9/30 9:39
 */
public class CouponContext {

    private CouponStrategy couponStrategy;

    public CouponContext(CouponStrategy couponStrategy) {
        this.couponStrategy = couponStrategy;
    }

    void execute(BigDecimal money) {
        couponStrategy.doActive(money);
    }
}

ConponClient.java (调用优惠券活动)

import java.math.BigDecimal;

/**
 * @author gcc
 * @version 1.0
 * @ClassName ConponMain
 * @description 高层模块调用的优惠券活动
 * @date 2021/9/30 9:40
 */
public class ConponClient {
    public static void main(String[] args) {
        // 打折价格券活动
        CouponContext dispatcher = new CouponContext(new DiscountCoupon());
        dispatcher.execute(new BigDecimal(300d));

        // 满减优惠券活动
        CouponContext fullMinusCoupon = new CouponContext(new FullMinusCoupon());
        fullMinusCoupon.execute(new BigDecimal(300d));
    }
}

总结

​ 整体来说策略模式还是比较简单的,就是我们常规理解的面向对象多态的特性,一个接口多个实现的方式,只不过多了一个封装对象而已。当然真正工作当中的业务逻辑肯定没有这么简单,这里仅仅是让我们了解到策略模式到底是什么样子的,仅仅是我们了解设计模式的前期基础阶段。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值