Delegate 委派模式和代理模式strategy的区别?策略模式如何实现消除多层if else?(下)

简介: Delegate 委派模式和代理模式strategy的区别?策略模式如何实现消除多层if else?(下)

案例2:订单支付策略案例


1dc618a0ed9580ce8bfa6facb208c08f.png


/**
 * 支付渠道
 * .
 */
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
    }
}


5d4c6812c8535adbb050f4ddf2e1bce8.png


切换成支付宝支付:

只要改一个参数:


MsgResult pay = order.pay(PayStrategy.JD_PAY);

1

46a9d80a6e05e4e3b19d57a0ee70bcdf.png


策略模式在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语句.


相关文章
|
1月前
|
设计模式 缓存 安全
【设计模式】单例模式:确保类只有一个实例
【设计模式】单例模式:确保类只有一个实例
23 0
|
6月前
|
设计模式 缓存 算法
JAVA设计模式14:策略模式,使算法的变化独立于使用它的客户端
JAVA设计模式14:策略模式,使算法的变化独立于使用它的客户端
|
7月前
继承(6种方式)以及优缺点
继承(6种方式)以及优缺点
|
4月前
|
设计模式 存储 安全
二十三种设计模式全面解析-享元模式(Flyweight Pattern)详解:构建高效共享的对象结构
二十三种设计模式全面解析-享元模式(Flyweight Pattern)详解:构建高效共享的对象结构
|
3天前
|
设计模式 Java C++
【C++高阶(八)】单例模式&特殊类的设计
【C++高阶(八)】单例模式&特殊类的设计
|
8月前
|
设计模式 算法 搜索推荐
设计模式—策略(Strategy)模式
设计模式—策略(Strategy)模式
131 1
|
6月前
|
设计模式 存储 Java
JAVA设计模式11:组合模式,以统一的方式处理单个对象和组合对象
JAVA设计模式11:组合模式,以统一的方式处理单个对象和组合对象
|
6月前
|
设计模式 Java 数据库连接
JAVA设计模式8:装饰模式,动态地将责任附加到对象上,扩展对象的功能
JAVA设计模式8:装饰模式,动态地将责任附加到对象上,扩展对象的功能
|
8月前
|
设计模式 Java
空对象模式【Java设计模式】
空对象模式【Java设计模式】
31 0
|
消息中间件 JavaScript 小程序
Java动态代理的两种方式及其优缺点
Java动态代理的两种方式及其优缺点