了解Spring中常见的设计模式-------------------委派模式,策略模式

委派模式(Delegate Pattern)

基本作用:负责任务的调度和分配任务,跟代理模式很像,可以看作是一种特殊情况下的静态代理的全权代理,但是代理模式更加注重过程,而委派模式更加注重结果

不属于GOF 23中设计模式之一

属于行为行模型

简单示例:(注册模式+工厂模式+委派模式)

public interface Coder {
    public void coding();
}


public class JavaCoder implements Coder {

    @Override
    public void coding() {
        System.out.println("use Java");
    }
}


public class PythonCoder implements Coder {
    @Override
    public void coding() {
        System.out.println("use python");
    }
}


public class Leader {

    private Map<String, Coder> job = new HashMap<>();

    public Leader() {
        job.put("JAVA", new JavaCoder());
        job.put("PYTHON", new PythonCoder());
    }

    public void doing(String commond) {
        commond = commond.toUpperCase();
        if (job.containsKey(commond)) {
            Coder coder = job.get(commond);
            coder.coding();
        } else {
            System.out.println("沒有该工种的员工");
        }
    }
}


public class Boss {

    public void commond(String commond) {
        Leader leader = new Leader();
        leader.doing(commond);
    }

    public static void main(String[] args) {
        Boss boss = new Boss();
        boss.commond("java");
        boss.commond("python");
    }
}


执行结果:
use Java
use python

策略模式(Strategy attern)

是指定义算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化不会影响到使用算法的用户

可以避免多重分支的if...else....和switch语句

使用场景:

1、假如系统中有很多的类,而他们的区别仅仅在于他们的行为不同

2、一个系统需要动态地在几种算法中选择一种

扫描二维码关注公众号,回复: 9674831 查看本文章

改造前的简单示例:

public interface PromotionStrategy {
    void execute();
}


public class GroupByPromotion implements PromotionStrategy {
    @Override
    public void execute() {
        System.out.println("组团促销活动!");
    }
}


public class EmptyPromotion implements PromotionStrategy {
    @Override
    public void execute() {
        System.out.println("没有促销活动!");
    }
}


public class CouponPromotion implements PromotionStrategy {
    @Override
    public void execute() {
        System.out.println("优惠券促销活动!");
    }
}


public class CashBackPromotion implements PromotionStrategy {
    @Override
    public void execute() {
        System.out.println("返现促销活动!");
    }
}


public class PromotionActivity {

    private PromotionStrategy promotionStrategy;

    public PromotionActivity(PromotionStrategy promotionStrategy) {
        this.promotionStrategy = promotionStrategy;
    }

    public void execute() {
        promotionStrategy.execute();
    }

}



public class StrategyTest {

    public static void main(String[] args){
        while (true) {
            System.out.println("请输入促销活动:");
            Scanner scanner = new Scanner(System.in);
            String strategy = scanner.nextLine();
            strategy = strategy.toUpperCase();
            PromotionStrategy promotionStrategy = null;
            if (strategy.equals("COUPON")) {
                promotionStrategy = new CouponPromotion();
            } else if (strategy.equals("CASHBACK")) {
                promotionStrategy = new CashBackPromotion();
            } else if (strategy.equals("GROUPBY")) {
                promotionStrategy = new GroupByPromotion();
            } else {
                promotionStrategy = new EmptyPromotion();
            }
            PromotionActivity promotionActivity = new PromotionActivity(promotionStrategy);
            promotionActivity.execute();
            System.out.println();
            System.out.println("是否退出:Y/N");
            String order = scanner.nextLine();
            if (order.equals("Y")) {
                break;
            }
        }

    }
}


执行结果为:
请输入促销活动:
coupon
优惠券促销活动!

是否退出:Y/N
n
请输入促销活动:
fd
没有促销活动!

是否退出:Y/N
Y

Process finished with exit code 0

结构关系图为:

使用工厂模式,单例模式,注册式模式,添加一个工厂类PromotionStrategyFactory 

改造后的代码示例:

public class PromotionStrategyFactory {

    private static Map<String, PromotionStrategy> PROMOTION_STRAREGY = new HashMap<>();

    static {
        PROMOTION_STRAREGY.put(StrategyName.EMPTY.name(), new EmptyPromotion());
        PROMOTION_STRAREGY.put(StrategyName.GROUPBY.name(), new GroupByPromotion());
        PROMOTION_STRAREGY.put(StrategyName.COUPON.name(), new CouponPromotion());
        PROMOTION_STRAREGY.put(StrategyName.CASHBACK.name(), new CashBackPromotion());
    }

    private PromotionStrategyFactory() {
    }

    public static PromotionStrategy execute(String strategy) {
        strategy = strategy.toUpperCase();
        if (PROMOTION_STRAREGY.containsKey(strategy)) {
            return PROMOTION_STRAREGY.get(strategy);
        } else {
            return PROMOTION_STRAREGY.get(StrategyName.EMPTY.name());
        }
    }

    public enum StrategyName {
        EMPTY("没有优惠活动"),

        GROUPBY("拼团活动"),

        COUPON("优惠券活动"),

        CASHBACK("返现活动");

        public String StrategyName;

        StrategyName(String StrategyName) {
            this.StrategyName = StrategyName;
        }
    }
}


public class StrategyTest {
    public static void main(String[] args) {
        while (true) {
            System.out.println("请输入促销活动:");
            Scanner scanner = new Scanner(System.in);
            String strategy = scanner.nextLine();
            PromotionActivity promotionActivity = new PromotionActivity(PromotionStrategyFactory.execute(strategy));
            promotionActivity.execute();
            System.out.println();
            System.out.println("是否退出:Y/N");
            String order = scanner.nextLine();
            if (order.equals("Y")) {
                break;
            }
        }
    }
}


执行结果:
请输入促销活动:
coupon
优惠券促销活动!

是否退出:Y/N
cashback
请输入促销活动:
cashback
返现促销活动!

是否退出:Y/N
n
请输入促销活动:
fdfeidaadfjaisfoa
没有促销活动!

是否退出:Y/N
Y

Process finished with exit code 0

结构关系图如下:

简单支付案例:

public abstract class Payment {

    public abstract String getName();

    public abstract BigDecimal queryRest();

    public abstract void pay(BigDecimal amount);

    public MsgResult pay(Long uid, BigDecimal amount) {
        BigDecimal bigDecimal = queryRest().subtract(amount);
        if (bigDecimal.signum() == -1) {
            return new MsgResult(500, "支付失败", "余额不足,余额为:" + queryRest().toString());
        }
        pay(amount);
        return new MsgResult(200, "支付成功", "余额为:" + queryRest());
    }
}


public class AliPay extends Payment {
    private static BigDecimal rest = new BigDecimal("3000");

    @Override
    public String getName() {
        return "支付宝支付";
    }

    @Override
    public BigDecimal queryRest() {
        return rest;
    }

    @Override
    public void pay(BigDecimal amount) {
        rest = rest.subtract(amount);
    }
}


public class JDPay extends Payment {
    private static BigDecimal rest = new BigDecimal("2000");

    @Override
    public String getName() {
        return "京东支付";
    }

    @Override
    public BigDecimal queryRest() {
        return rest;
    }

    @Override
    public void pay(BigDecimal amount) {
        rest = rest.subtract(amount);
    }
}


public class UnionPay extends Payment {

    private static BigDecimal rest = new BigDecimal("600");

    @Override
    public String getName() {
        return "银联支付";
    }

    @Override
    public BigDecimal queryRest() {
        return rest;
    }

    @Override
    public void pay(BigDecimal amount) {
        rest = rest.subtract(amount);
    }
}


public class WechatPay extends Payment {
    private static BigDecimal rest = new BigDecimal("900");

    @Override
    public String getName() {
        return "微信支付";
    }

    @Override
    public BigDecimal queryRest() {
        return rest;
    }

    @Override
    public void pay(BigDecimal amount) {
        rest = rest.subtract(amount);
    }
}


public class PayStrategyFactory {

    private static Map<String, Payment> paymentMap = new HashMap<>();

    private PayStrategyFactory() {
    }

    public static Payment getPayMent(String strategyName) {
        strategyName = strategyName.toUpperCase();
        if (paymentMap.containsKey(strategyName)) {
            return paymentMap.get(strategyName);
        }
        return paymentMap.get(StrategyName.ALI.name());
    }

    static {
        paymentMap.put(StrategyName.ALI.name(), new AliPay());
        paymentMap.put(StrategyName.JD.name(), new JDPay());
        paymentMap.put(StrategyName.WECHAT.name(), new WechatPay());
        paymentMap.put(StrategyName.UNION.name(), new UnionPay());
    }

    public enum StrategyName {
        ALI("支付宝支付"),

        JD("京东支付"),

        WECHAT("微信支付"),

        UNION("银联支付");

        private String strategyName;

        StrategyName(String strategyName) {
            this.strategyName = strategyName;
        }
    }
}


public class MsgResult {

    private int code;
    private String msg;
    private Object data;

    public MsgResult(int code, String msg, Object data) {
        this.code = code;
        this.msg = msg;
        this.data = data;
    }

    @Override
    public String toString() {
        return "MsgResult{" + "code=" + code + ", msg='" + msg + '\'' + ", data=" + data + '}';
    }
}


public class Order {

    private Long uid;
    private String orderId;
    private BigDecimal amount;

    public Order(BigDecimal amount) {
        this.amount = amount;
    }

    public Order(Long uid, String orderId, BigDecimal amount) {
        this.uid = uid;
        this.orderId = orderId;
        this.amount = amount;
    }

    public MsgResult pay(String strategy) {
        Payment payment = PayStrategyFactory.getPayMent(strategy);
        return payment.pay(this.uid, this.amount);
    }

    @Override
    public String toString() {
        return "Order{" + "uid=" + uid + ", orderId='" + orderId + '\'' + ", amount=" + amount + '}';
    }
}



public class PayStrategyTest {

    public static void main(String[] args) {
        while (true) {
            System.out.println("请输入支付方式:");
            Scanner scanner = new Scanner(System.in);
            String payWay = scanner.nextLine();
            System.out.println("请输入支付金额:");
            String amountStr = scanner.nextLine();
            Order order = new Order(19L, "", new BigDecimal(amountStr));
            MsgResult msgResult = order.pay(payWay);
            System.out.println(msgResult.toString());

            System.out.println("是否继续:Y/N");
            String judge = scanner.nextLine();
            if (judge.equals("N")) {
                break;
            }
        }
    }
}


执行结果为:
请输入支付方式:
ali
请输入支付金额:
100
MsgResult{code=200, msg='支付成功', data=余额为:2900}
是否继续:Y/N
Y
请输入支付方式:
ali
请输入支付金额:
100
MsgResult{code=200, msg='支付成功', data=余额为:2800}
是否继续:Y/N
Y
请输入支付方式:
wechat
请输入支付金额:
100
MsgResult{code=200, msg='支付成功', data=余额为:800}
是否继续:Y/N
Y
请输入支付方式:
ali
请输入支付金额:
300
MsgResult{code=200, msg='支付成功', data=余额为:2500}
是否继续:Y/N


相关类的结构关系图如下所示:

策略模式的优点:

1、符合开闭原则

2、避免使用多重条件转移语句,如:if...else...语句,switch语句

3、使用策略模式可以提高算法的保密性和安全性。

策略模式的缺点:

1、客户端必须知道所有的策略,并且自行决定使用哪一个策略类

2、代码中会产生非常多的策略,增加了维护难度

实现简单的DispatcherServlet,示例如下:

public class MemberController {

    public void getMemberById(String mid){

    }
}


public class OrderController {

    public void getOrderById(String mid){

    }
}


public class SystemController {

    public void logout(String mid){

    }
}


public class SimpleDispatcherServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doDispatcher(req, resp);
    }
 
    private void doDispatcher(HttpServletRequest req, HttpServletResponse resp) {
        String uri = req.getRequestURI();
        String mid = req.getParameter("mid");
        if (uri.equals("getMemberById")) {
            new MemberController().getMemberById(mid);
        } else if (uri.equals("getOrderById")) {
            new OrderController().getOrderById(mid);
        } else if (uri.equals("logout")) {
            new SystemController().logout(mid);
        } else {
            try {
                resp.getWriter().write("404 not found");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

使用策略模式实现简单的DispatcherServlet,示例如下:

public class SimpleDispatcherServlet extends HttpServlet {

    private List<Hander> requestMapping = new ArrayList<>();

    @Override
    public void init() throws ServletException {
        Class<?> clzz = MemberController.class;
        try {
            requestMapping.add(
                new Hander().setController(clzz.newInstance()).setMethod(clzz.getMethod("getMemberById", String.class))
                    .setUrl("/member/getMemberById"));
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doDispatcher1(req, resp);
    }

    private void doDispatcher1(HttpServletRequest req, HttpServletResponse resp) {
        String uri = req.getRequestURI();
        String mid = req.getParameter("mid");
        Hander hander = null;
        for (Hander handerInner : requestMapping) {
            if (handerInner.getUrl().equals(uri)) {
                hander = handerInner;
                break;
            }
        }

        if (hander==null){
            try {
                resp.getWriter().write("404 not found");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        try {
            Object object = hander.getMethod().invoke(hander.getController(), mid);
            resp.getWriter().write(object.toString());
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    class Hander {
        private Object controller;
        private Method method;
        private String url;

        public Object getController() {
            return controller;
        }

        public Hander setController(Object controller) {
            this.controller = controller;
            return this;
        }

        public Method getMethod() {
            return method;
        }

        public Hander setMethod(Method method) {
            this.method = method;
            return this;
        }

        public String getUrl() {
            return url;
        }

        public Hander setUrl(String url) {
            this.url = url;
            return this;
        }
    }
}
发布了35 篇原创文章 · 获赞 0 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/tealala/article/details/103565253
今日推荐