策略模式,实质就是封装了一些算法,让算法可以互相替换,用户可以自由选择这些算法进行操作。大话设计模式一书中,针对策略模式的引出写的还是比较不错的,可以借鉴。策略模式本身理解起来没什么难点,但是在实际应用中其本身主要结合工厂模式一起使用。Java中常用的集合比较器,就是策略模式的一种应用,除此之外,Spring中很多BeanFactory的实现,在配置BeanFactory的时候,选择何种factory,这其实就是一种策略的选择,也算是策略模式的一种。针对策略模式其他的总结,已经有前辈做的非常不错了,如这篇博客:最好的策略模式讲解文章,下图是策略模式的结构图,依旧来自大话设计模式一书。
先直接上实例吧
Payment接口
public interface Payment {
//写在这里用户就不用去new相应的支付对象
//种类每增加一个支付渠道,这里就要被维护一次。
// public final static Payment ALI_PAY = new Alipay();
// public final static Payment UnionPay = new UnionPay();
// public final static Payment WeChatPay = new WeChatPay();
public PayState pay(String uid,double amount);
}
Alipay类,这里只贴出这个类,其余三个不再贴出
public class Alipay implements Payment{
public PayState pay(String uid, double amount) {
System.out.println("欢迎使用支付宝进行支付");
System.out.println("查询账户余额,开始扣款");
return new PayState(200,"成功支付",String.valueOf(amount));
}
}
PayState类,其实就是一个返回结果,作用和一个字符串差不多
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;
}
public String toString(){
return ("支付状态:["+code+"],"+msg+"[ 交易详情:"+data);
}
}
Order订单类,其中有结算方法
public class Order {
private String uid;
private String orderId;
private double amount;
public Order(String uid,String orderId,double amount) {
this.amount = amount;
this.uid = uid;
this.orderId = orderId;
}
// 订单的结算方法
// public PayState pay(Payment payment){
// return payment.pay(this.uid,this.amount);
// }
//这个参数完全可以用接口代替,但是这里用到的是枚举,为什么没有用接口
//能完美的解决switch的过程,这里就不用根据用户选择的类型来进行判断了
//不用写一长串的判断语句,不需要写if-else进行支付渠道的判断
public PayState pay(PayType payType){
return payType.getPayment().pay(this.uid,this.amount);
}
}
注释代码中,是没有使用枚举的时候,如果这个时候新增加一种支付方式:MeiTuanPay,Payment这个接口就需要重新维护一次,在其中增加一个常量 public final static Payment MEITUAN_PAY = new MeiTuanPay();这样在实际生产过程中无疑是不好的,所以这里就采用了枚举,既避免了工厂模式的繁琐,也能巧妙的实现指定的功能。
PayType的枚举,其中的getPayment能根据选中的枚举类型,创建指定的支付类型
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 getPayment(){
return this.payment;
}
}
使用了PayType枚举之后,如果新增了Meituan_Pay,只需要在其中增加MEITUAN_PAY(new MeituanPay())即可
测试类:
public class PayStrategyTest {
public static void main(String[] args) {
Order order = new Order("1","2018030300100001",25.5);
//开始支付,微信支付,支付宝,银联卡,京东白条
//每个渠道支付的具体算法是不一样的,但是基本算法是固定的
//System.out.println(order.pay(new Alipay()));
System.out.println(order.pay(PayType.ALI_PAY));
System.out.println(order.pay(PayType.UNION_PAY));
System.out.println(order.pay(PayType.WECHAT_PAY));
System.out.println(order.pay(PayType.JD_PAY));
}
}
测试结果如下:
策略模式本身比较好理解,但通常其并不单独使用,而是结合工厂模式进行使用,本文中的实例利用枚举,其实也是工厂的一种简单表示