个人感悟之策略模式
策略模式
策略模式到底是一个什么样子的意思呢?我们可以拿出一些例子来进行阐述:把商品添加到购物车里面去,然后我们会下单,根据金额进行支付,支付的方式也有很多比如支付宝、银行卡等,然后卖家发货,通过物流送到我们手里。这是一套我们熟悉的在淘宝上买东西的流程。策略模式就是封装算法,让算法可以相互替换,不影响使用算法的用户,用户本身知道他要采用什么算法去计算,就像用户去选择支付方式一样。我们可以使用在下面用代码实现一下
订单类
我们首先建立一个订单类,他包含的项目包括用户ID,订单ID和订单金额,这对于我们很熟悉,因此实现也不难。
public class Order { private String uId; private String orderId; double amount; public Order(String uId, String orderId, double amount) { this.uId = uId; this.orderId = orderId; this.amount = amount; } public PayState pay(Payment payment) { return payment.pay(this.uId,this.amount); } }
接着就是支付方式类,我先定义一个接口,然后让每个支付方式去实现它。
public interface Payment { public PayState pay(String uId,double amount); } public class AliPay implements Payment { public PayState pay(String uId, double amount) { System.out.println("现在正在使用支付宝"); System.out.println("您的余额充足,正在扣费"); return new PayState(200,amount,"支付成功"); } } public class WeChatPay implements Payment { public PayState pay(String uId, double amount) { System.out.println("正在使用微信支付"); //这里我不做余额判断,先设置余额不足的情况 System.out.println("您的余额不足,扣费失败"); return new PayState(90,100,"请选择其他支付方式"); } }
然后就是一个支付状态的类,主要参数是余额,订单金额和支付信息。
public class PayState { private int code; private Object data; private String msg; public PayState(int code, Object data, String msg) { this.code = code; this.data = data; this.msg = msg; } @Override public String toString() { return "支付状态:{" + "code=" + code + ", 交易详情=" + data + ", msg='" + msg + '\'' + '}'; } }
最后我通过一个测试类来验证一下是不是符合逻辑。
public class PayStrategyTest { public static void main(String[] args) { Order order = new Order("1","cnblogjolivan",100); //用户选择支付方式:支付宝、银联卡、微信支付等,每个渠道具体支付的算法不一样,基本的算法是固定的,但是有选择权。 System.out.println(order.pay(new AliPay())); System.out.println(order.pay(new WeChatPay())); } } ----------------------------------------------------------------------- 现在正在使用支付宝 您的余额充足,正在扣费 支付状态:{code=200, 交易详情=100.0, msg='支付成功'} 正在使用微信支付 您的余额不足,扣费失败 支付状态:{code=90, 交易详情=100, msg='请选择其他支付方式'}
但是这样我总感觉用户在选择支付方式的时候,并不能满足用户选择支付方式,因为用户根本就不知道有哪些支付方式,于是我又想到了一个思路,就是在接口里直接包装支付方式,返回一个支付类的实例。
public interface Payment { public final Payment Ali_Pay = new AliPay(); public final Payment WeChat_Pay = new WeChatPay(); public PayState pay(String uId,double amount); }
但是这样的方式,如果我新增一个支付方式,那么就要修改这个接口,不满足开闭原则,因此这个方法不是很好。怎么样能保证在拓展支付方式的时候,不破坏开闭原则呢?可以用到枚举方法,因为这样我们在增加支付方式的时候,就增加一个支付的入口就可以了。
public enum PayType { Ali_Pay(new AliPay()), WeChat_Pay(new AliPay()); private Payment payment;
PayType(Payment payment){ this.payment = payment; } public Payment getPayment() { return payment; } }
然后再回到我们的测试类,这样就可以满足我们的要求了。
public class PayStrategyTest { public static void main(String[] args) { Order order = new Order("1","cnblogjolivan",100); //用户选择支付方式:支付宝、银联卡、微信支付等,每个渠道具体支付的算法不一样,基本的算法是固定的,但是有选择权。 System.out.println(order.pay(PayType.Ali_Pay)); } }
这样用户就可以获取所有的支付方式,但不会知道具体支付方式的核心代码。
其实我个人感觉策略模式和工厂模式很像,只不过工厂模式侧重对象实例的区别,而策略模式侧重执行的过程不一样。