今天开始咱们专题的第七课了。本章节将介绍:你写的代码中是否以为很臃肿,程序中有大量的if...else,想优化代码,精简程序逻辑,提高代码的可读性,这章节将介绍如何经过委派模式、策略模式让你代码更优雅,消除程序大量冗余的代码。本章节参考资料书籍《Spring 5核心原理》中的第一篇 Spring 内功心法(Spring中经常使用的设计模式)(没有电子档,都是我取其精华并结合本身的理解,一个字一个字手敲出来的)。java
委派模式不属于GOF23种设计模式中。委派模式(Delegate Pattern)的基本做用就是负责任务的调用和分配任务,跟代理模式很像,能够看作是一种特殊状况下的静态代理的全权代理,可是代理模式注重过程,而委派模式注重结果。委派模式在Spring中应用很是多,你们经常使用的DispatcherServlet其实就是用到了委派模式。现实生活中也常有委派的场景发生,例如:老板(Boss)给项目经理(Leader)下达任务,项目经理会根据实际状况给每一个员工派发工做任务,待员工把工做任务完成以后,再由项目经理汇报工做进度和结果给老板。咱们用代码来模拟下这个业务场景,先来看一下类图:算法
建立员工接口设计模式
package com.study.demo2; /** * @ClassName IEmployee * @Deacription 员工接口 * @Author wang.zhong.yuan * @Date 2020/7/9 16:36 * @Version 1.0 **/ public interface IEmployee { /** * 须要作的工做 * @param command */ void doingSomeThing(String command); }
员工A实现类安全
package com.study.demo2; /** * @ClassName EmployeeA * @Deacription 员工A * @Author wang.zhong.yuan * @Date 2020/7/9 16:38 * @Version 1.0 **/ public class EmployeeA implements IEmployee { public void doingSomeThing(String command) { System.out.println("我是员工A,须要作:"+command); } }
员工B实现类微信
package com.study.demo2; /** * @ClassName EmployeeB * @Deacription 员工B * @Author wang.zhong.yuan * @Date 2020/7/9 16:48 * @Version 1.0 **/ public class EmployeeB implements IEmployee { public void doingSomeThing(String command) { System.out.println("我是员工B,我要作:"+command); } }
领导类ide
package com.study.demo2; import java.util.HashMap; import java.util.Map; /** * @ClassName Leader * @Deacription 领导类 * @Author wang.zhong.yuan * @Date 2020/7/9 16:51 * @Version 1.0 **/ public class Leader implements IEmployee { private Map<String,IEmployee> underling = new HashMap<String, IEmployee>(); public Leader() { underling.put("注册功能",new EmployeeA()); underling.put("登录功能",new EmployeeB()); } /** * 本身不作事,委派给对应的员工去作 * @param command */ public void doingSomeThing(String command) { underling.get(command).doingSomeThing(command); } }
建立BOSS类,安排工做给Leader测试
package com.study.demo2; /** * @ClassName Boss * @Deacription TODO * @Author 19054253 * @Date 2020/7/9 17:03 * @Version 1.0 **/ public class Boss { public void command(String command, Leader leader){ leader.doingSomeThing(command); } //测试功能 public static void main(String[] args) { //客户请求(Boss)、委派者(Leader)、被被委派者(Target) //委派者要持有被委派者的引用 //代理模式注重的是过程, 委派模式注重的是结果 //策略模式注重是可扩展(外部扩展),委派模式注重内部的灵活和复用 //委派的核心:就是分发、调度、派遣 //委派模式:就是静态代理和策略模式一种特殊的组合 Boss boss = new Boss(); Leader leader = new Leader(); boss.command("登录功能",leader); } }
输出结果微信支付
经过上面的代码,生动地还原了项目经理分配工做的业务场景,也是委派模式的生动体现。优化
策略模式(Strategy Pattern)是指定义了算法家族、分别封装起来,让它们之间能够互相替换,此模式让算法的变化不会影响到使用算法的用户。假如系统中有不少类,而他们的区别仅仅在于他们的行为不一样。一个系统须要动态地在几种算法中选择一种,均可以用策略模式实现。ui
一个常见的应用场景就是你们在下单支付时会提示选择支付方式,若是用户未选,系统也会默认好推荐的支付方式进行结算。来看一下类图,下面咱们用策略模式来模拟此业务场景:
建立支付状态类:
package com.study.demo3; /** * @ClassName PayState * @Deacription 支付状态 * @Author wang * @Date 2020/7/9 17:48 * @Version 1.0 **/ public class PayState { private int code; private Object data; private String message; public PayState(int code, Object data, String message) { this.code = code; this.data = data; this.message = message; } @Override public String toString() { return "PayState{" + "code=" + code + ", data=" + data + ", message='" + message + '\'' + '}'; } }
建立支付接口
package com.study.demo3; /** * @ClassName Payment * @Deacription 支付渠道 * @Author wang * @Date 2020/7/9 19:12 * @Version 1.0 **/ public interface IPayment { /** * 获取支付类型 * @return */ String getName(); /** * 查询余额 * @param uid * @return */ double queryBalance(String uid); /** * 支付 * @param uid * @param amount * @return */ PayState pay(String uid,double amount); }
建立支付抽象类,完成一些通用的代码:
package com.study.demo3; /** * @ClassName AbstractPayment * @Deacription 支付抽象类 * @Author wang * @Date 2020/7/9 19:16 * @Version 1.0 **/ public abstract class AbstractPayment implements IPayment{ public PayState pay(String uid, double amount) { if (queryBalance(uid) < amount){ return new PayState(-1,"支付失败","余额不足"); } return new PayState(200,"支付成功","共计支付:"+amount); } }
建立阿里支付渠道
package com.study.demo3; /** * @ClassName AliPay * @Deacription 支付宝支付 * @Author wang * @Date 2020/7/9 19:20 * @Version 1.0 **/ public class AliPay extends AbstractPayment { public String getName() { return "支付宝支付"; } public double queryBalance(String uid) { return 500; } }
建立京东支付渠道
package com.study.demo3; /** * @ClassName JDPay * @Deacription 京东支付 * @Author wang * @Date 2020/7/9 19:22 * @Version 1.0 **/ public class JDPay extends AbstractPayment { public String getName() { return "京东支付"; } public double queryBalance(String uid) { return 900; } }
建立微信支付渠道
package com.study.demo3; /** * @ClassName WXPay * @Deacription 微信支付 * @Author wang * @Date 2020/7/9 19:23 * @Version 1.0 **/ public class WXPay extends AbstractPayment { public String getName() { return "微信支付"; } public double queryBalance(String uid) { return 256; } }
package com.study.demo3; /** * @ClassName Order * @Deacription 订单类 * @Author wang * @Date 2020/7/9 19:35 * @Version 1.0 **/ 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(){ return pay(PayStrategy.DEFAULT_PAY); } public PayState pay(String payKey){ IPayment payment = PayStrategy.get(payKey); System.out.println("欢迎使用" + payment.getName()); System.out.println("本次交易金额为:" + amount + ",开始扣款..."); return payment.pay(uid,amount); } //测试代码 public static void main(String[] args) { Order order = new Order("123", "AB123", 400); //这个值是在支付的时候才决定用哪一个值 用户本身决定 order.pay("AliPay"); } }
输出结果:
但愿经过你们耳熟能详的业务场景来举例,让小伙伴们更深入地理解策略模式。
优势:
一、策略模式符合开闭原则。
二、避免使用多重条件转移语句,如if...else...语句、switch语句
三、使用策略模式能够提升算法的保密性和安全性。
缺点: 一、客户端必须知道全部的策略,而且自行决定使用哪个策略类。 二、代码中会产生很是多策略类,增长维护难度。