案例2:订单支付策略案例
/** * 支付渠道 * . */ public abstract class Payment { //支付类型 public abstract String getName(); //查询余额 protected abstract double queryBalance(String uid); //扣款支付 public MsgResult pay(String uid, double amount) { if(queryBalance(uid) < amount){ return new MsgResult(500,"支付失败","余额不足"); } return new MsgResult(200,"支付成功","支付金额:" + amount); } }
public class JDPay extends Payment { public String getName() { return "京东白条"; } protected double queryBalance(String uid) { return 500; } }
public class AliPay extends Payment { public String getName() { return "支付宝"; } protected double queryBalance(String uid) { return 900; } }
public class UnionPay extends Payment { public String getName() { return "银联支付"; } protected double queryBalance(String uid) { return 120; } }
public class WechatPay extends Payment { public String getName() { return "微信支付"; } protected double queryBalance(String uid) { return 256; } }
策略类(最重要)
public class PayStrategy { public static final String ALI_PAY = "AliPay"; public static final String JD_PAY = "JdPay"; public static final String UNION_PAY = "UnionPay"; public static final String WECHAT_PAY = "WechatPay"; public static final String DEFAULT_PAY = ALI_PAY; private static Map<String, Payment> payStrategy = new HashMap<String, Payment>(); static { payStrategy.put(ALI_PAY, new AliPay()); payStrategy.put(WECHAT_PAY, new WechatPay()); payStrategy.put(UNION_PAY, new UnionPay()); payStrategy.put(JD_PAY, new JDPay()); } public static Payment get(String payKey) { if (!payStrategy.containsKey(payKey)) { return payStrategy.get(DEFAULT_PAY); } return payStrategy.get(payKey); } }
支付完后的响应对象:
public class MsgResult { private int code; private Object data; private String msg; public MsgResult(int code, String msg, Object data) { this.code = code; this.data = data; this.msg = msg; } public String toString(){ return ("支付状态:[" + code + "]," + msg + ",交易详情:" + data); } }
测试:
public class PayStrategyTest { public static void main(String[] args) { //省略把商品添加到购物车,再从购物车下单 //直接从点单开始 Order order = new Order("1","20180311001000009",324.45); //开始支付,选择微信支付、支付宝、银联卡、京东白条、财付通 //每个渠道它支付的具体算法是不一样的 //基本算法固定的 MsgResult pay = order.pay(PayStrategy.JD_PAY); //这个值是在支付的时候才决定用哪个值 // System.out.println(order.pay(PayStrategy.ALI_PAY)); System.out.println(pay); //java中的应用 // Arrays.sort(); //Resource // InstantiationStrategy } }
切换成支付宝支付:
只要改一个参数:
MsgResult pay = order.pay(PayStrategy.JD_PAY);
1
策略模式在JDK 源码中的体现
Arrays 类的parallelSort 方法等
compare()方法,就是一个策略抽象实现. public class Arrays { public static <T> void parallelSort(T[] a, int fromIndex, int toIndex, Comparator<? super T> cmp) { } }
public interface Comparator<T> { int compare(T o1, T o2); }
策略模式的优缺点
优点:
1、策略模式符合开闭原则。
2、避免使用多重条件转移语句,如if…else…语句、switch 语句
3、使用策略模式可以提高算法的保密性和安全性。
缺点:
1、客户端必须知道所有的策略,并且自行决定使用哪一个策略类。
2、代码中会产生非常多策略类,增加维护难度。
委派模式与策略模式综合应用
刚才的委派模式中的dispatchsevlet:实际项目中一定不止这几个Controller,往往是成千上万个Controller,显然,我们不能写成千上万个if…else… 。那么我们如何来改造呢,用策略模式:
public class DispatcherServlet extends HttpServlet { private List<Handler> handlerMapping = new ArrayList<Handler>(); @Override public void init() throws ServletException { try { Class<?> memberControllerClass = MemberController.class; handlerMapping.add(new Handler() .setController(memberControllerClass.newInstance()) .setMethod(memberControllerClass.getMethod("getMemberById", new Class[]{String.class})) .setUrl("/web/getMemberById.json")); } catch (Exception e) { } } @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { try { doDispatch(req, resp); } catch (Exception e) { e.printStackTrace(); } } private void doDispatch(HttpServletRequest request, HttpServletResponse response) throws IOException { //1、获取用户请求的url // 如果按照J2EE的标准、每个url对对应一个Serlvet,url由浏览器输入 String uri = request.getRequestURI(); //2、Servlet拿到url以后,要做权衡(要做判断,要做选择) // 根据用户请求的URL,去找到这个url对应的某一个java类的方法 //3、通过拿到的URL去handlerMapping(我们把它认为是策略常量) Handler handle = null; for (Handler h : handlerMapping) { if (uri.equals(h.getUrl())) { handle = h; break; } } //4、将具体的任务分发给Method(通过反射去调用其对应的方法) Object object = null; try { object = handle.getMethod().invoke(handle.getController(), request.getParameter("mid")); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } //5、获取到Method执行的结果,通过Response返回出去 response.getWriter().write(""); } class Handler { private Object controller; private Method method; private String url; public Object getController() { return controller; } public Handler setController(Object controller) { this.controller = controller; return this; } public Method getMethod() { return method; } public Handler setMethod(Method method) { this.method = method; return this; } public String getUrl() { return url; } public Handler setUrl(String url) { this.url = url; return this; } } }
总结:
1.使用委派模式,可以写出更加优雅的代码。
2.策略模式,可以消除程序中大量的冗余代码和多重条件转移语句。
3.委派模式属于行为型模式,基本作用就是负责任务的调度和分配任务,跟代理模式很像,可以看做是一种特殊情况下的静态代理的全权代理,但是代理模式注重过程,而委派模式注重结果。
4.策略模式是行为型模式:(Strategy Pattern)是指定义了算法家族、分别封装起来,让它们之间可以互相替换,此模式让算法的变化不会影响到使用算法的用户。可以避免多重分支的if…else…和switch语句.