常用设计模式之策略模式

190 阅读3分钟

定义

策略模式作为一种软件设计模式,指对象有某个行为,但是在不同的场景中,该行为有不同的实现算法。

  • 定义了一组算法(业务规则);
  • 封装了每个算法;
  • 这族的算法可互换代替(interchangeable)

使用场景

  • 如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为。
  • 一个系统需要动态地在几种算法中选择一种。
  • 如果一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现。

注意事项

如果一个系统的策略多于四个,就需要考虑使用混合模式,解决策略类膨胀的问题。

实现

已支付场景为例子,我们将创建一个定义支付活动的 Payment 接口和实现了 Payment 接口的实体策略类。Order 是一个使用了某种策略的类。

定义 PayState 状态

/**
 * 支付完成以后的状态
 * Created by Tom on 2018/3/11.
 */
public class PayState {
    private int code;
    private Object data;
    private String msg;

    public PayState(int code, String msg,Object data) {
        this.code = code;
        this.data = data;
        this.msg = msg;
    }

    public String toString(){
        return ("支付状态:[" + code + "]," + msg + ",交易详情:" + data);
    }
}

定义Payment接口

/*
* 支付渠道
*/
public interface Payment {
    public PayState pay(String uid, double amount);
}

实现Payment接口

AliPay

public class AliPay implements Payment {
    @Override
    public PayState pay(String uid, double amount) {
        System.out.println("欢迎使用支付宝");
        System.out.println("查询账户余额,开始扣款");
        return new PayState(200,"支付成功",amount);
    }
}

JDPay

public class JDPay implements Payment {
    @Override
    public PayState pay(String uid, double amount) {
        System.out.println("欢迎使用京东白条");
        System.out.println("查询账户余额,开始扣款");
        return new PayState(200,"支付成功",amount);
    }
}

UnionPay

public class UnionPay implements Payment {
    @Override
    public PayState pay(String uid, double amount) {
        System.out.println("欢迎使用银联卡支付");
        System.out.println("查询账户余额,开始扣款");
        return new PayState(200,"支付成功",amount);
    }
}

WechatPay

public class WechatPay implements Payment {
    @Override
    public PayState pay(String uid, double amount) {
        System.out.println("欢迎使用微信支付");
        System.out.println("直接从微信红包扣款");
        return new PayState(200,"支付成功",amount);
    }
}

定义一个枚举来维护这些策略

public enum PayType {
    ALI_PAY(new AliPay()),
    WECHAT_PAY(new WechatPay()),
    UNION_PAY(new UnionPay()),
    JD_PAY(new JDPay());

    private Payment payment;
    PayType(Payment payment){
        this.payment = payment;
    }
    public Payment get(){ return  this.payment;}
}

定义Order类来使用策略

public class Order {
    private String uid;
    private String orderId;
    private double amount;

    public Order(String uid,String orderId,double amount){
        this.uid = uid;
        this.orderId = orderId;
        this.amount = amount;
    }

    //使用枚举解决了switch的过程,不需要在代码逻辑中写switch了
    //更不需要写if else if
    public PayState pay(PayType payType){
        return payType.get().pay(this.uid,this.amount);
    }
}

Order 实例使用不同的策略

Order类通过调用pay()方法,并传入PayType 枚举值来选择不同的策略。

public class PayStrategyTest {
    public static void main(String[] args) {
        //省略把商品添加到购物车,再从购物车下单
        //直接从订单开始
        Order order = new Order("1","20180311001000009",324.45);

        //开始支付,选择微信支付、支付宝、银联卡、京东白条、财付通
        //每个渠道它支付的具体算法是不一样的
        //基本算法固定的

        //使用哪一种算法策略是在支付的时候才决定
        System.out.println(order.pay(PayType.WECHAT_PAY));
    }
}