zoukankan      html  css  js  c++  java
  • 二十:职责链模式详解(类似于spring的hangler处理请求)

    定义:为了避免请求的发送者和接收者之间的耦合关系,使多个接受对象都有机会处理请求。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。

    “看这个定义,就是将一堆可以处理请求的对象连成一条链,然后一个一个试着处理请求。这好像是可以解决麦当劳订餐的问题的,我先来看看我刚才苦B的订餐过程是什么样子的。” “首先应该有一个麦当劳的分店的类,它的主要功能是可以订餐。”

     “先来看看职责链模式的类图,这样比较好设计。”

     “类图还是比较简单的啊,有一个通用的接口,然后就是若干个具体的处理者。按照现在麦当劳的情况来说,接口里handleRequest方法其实就是order(订餐)方法了,而setSuccessor方法,则是用来设置职责链的下一个处理者。”

    “对于麦当劳的问题来说,每一个分店就是具体的处理者了,主要的改动应该是抽象出来一个接口以及职责链的连接过程,而刚才发送订单的时候是拆分成方法参数传递给订餐方法的,现在最好是把订单做成一个数据类。”

    复制代码
    package com.chain;
    
    import java.util.Map;
    
    //订单类(相当于request,其实就是封装一个请求)
    public class Order {
    
        private int x;
        private int y;
        private Map<String, Integer> order;
        
        public Order(int x, int y, Map<String, Integer> order) {
            super();
            this.x = x;
            this.y = y;
            this.order = order;
        }
    
        public int getX() {
            return x;
        }
    
        public void setX(int x) {
            this.x = x;
        }
    
        public int getY() {
            return y;
        }
    
        public void setY(int y) {
            this.y = y;
        }
    
        public Map<String, Integer> getOrder() {
            return order;
        }
    
        public void setOrder(Map<String, Integer> order) {
            this.order = order;
        }
        
    }
    复制代码

                    “下面便应该是分店接口了,它有两个方法,和类图当中的方法类似,只是名称略有改变。”

    复制代码
    package com.chain;
    //分店接口(相当于Hanlder)
    public interface Subbranch {
    
        void setSuccessor(Subbranch subbranch);
        
        boolean handleOrder(Order order);
        
    }
    复制代码

                    “下面便是麦当劳分店的实现类了,它主要的改变是添加了一个属性(下一个分店),这应该就是链形成的基石了。”

    复制代码
    package com.chain;
    
    import java.util.Collections;
    import java.util.Map;
    
    //麦当劳分店
    public class McSubbranch implements Subbranch{
        
        private final static int MIN_DISTANCE = 500;//假设是500米以内送餐
        
        private static int count;//类计数
        
        private final int number;//分店号
        
        private int x;//分店的横坐标,用于判断距离
        
        private int y;//分店的纵坐标,用于判断距离
        
        private Map<String, Integer> menu;//菜单
        
        private Subbranch nextSubbranch;//下一家分店
        
        public McSubbranch(int x, int y, Map<String, Integer> menu) {
            super();
            this.x = x;
            this.y = y;
            this.menu = menu;
            number = ++count;
        }
        //设置下一家分店
        public void setSuccessor(Subbranch subbranch) {
            this.nextSubbranch = subbranch;
        }
        //按照职责链处理订单
        public boolean handleOrder(Order order){
            //如果距离小于500米并且订单中的食物不缺货,则订单成功,否则失败
            if (CommonUtils.getDistance(order.getX(), order.getY(), this.x, this.y) < MIN_DISTANCE && !CommonUtils.outOfStock(menu, order.getOrder())) {
                for (String name : order.getOrder().keySet()) {
                    menu.put(name, menu.get(name) - order.getOrder().get(name));
                }
                System.out.println("订餐成功,接受订单的分店是:" + this);
                return true;
            }
            if (nextSubbranch == null) {
                return false;
            }
            return nextSubbranch.handleOrder(order);
        }
    
        public Map<String, Integer> getMenu() {
            return Collections.unmodifiableMap(menu);
        }
        
        public Subbranch getNextSubbranch() {
            return nextSubbranch;
        }
        
        public String toString() {
            return "麦当劳分店第" + number + "个";
        }
        
        
    }
    复制代码

                   “handleOrder方法中的逻辑就是职责链的精髓了,它会试图处理请求,如果处理不了,则交给链中的下一个分店。刚才用的CommonUtils应该不用变了。下面就看下有了职责链模式之后,我的订餐方式吧。”

    复制代码
    package com.chain;
    
    import java.util.HashMap;
    import java.util.Map;
    
    public class Client {
    
        public static void main(String[] args) {
            //假设初始菜单都是以下这些东西
            Map<String, Integer> menu = new HashMap<String, Integer>();
            menu.put("汉堡", 5);
            menu.put("薯条", 5);
            menu.put("可乐", 5);
            menu.put("雪碧", 5);
            //假设有5个分店
            Subbranch mcSubbranch1 = new McSubbranch(0, 0, new HashMap<String, Integer>(menu));
            Subbranch mcSubbranch2 = new McSubbranch(100, 120, new HashMap<String, Integer>(menu));
            Subbranch mcSubbranch3 = new McSubbranch(-100, -120, new HashMap<String, Integer>(menu));
            Subbranch mcSubbranch4 = new McSubbranch(1000, 20, new HashMap<String, Integer>(menu));
            Subbranch mcSubbranch5 = new McSubbranch(-500, 0, new HashMap<String, Integer>(menu));
            
            //以下设置职责链
            mcSubbranch4.setSuccessor(mcSubbranch5);
            mcSubbranch3.setSuccessor(mcSubbranch4);
            mcSubbranch2.setSuccessor(mcSubbranch3);
            mcSubbranch1.setSuccessor(mcSubbranch2);
            //小左开始订餐,假设小左的坐标是900,20 
            Map<String, Integer> order = new HashMap<String, Integer>();
            order.put("汉堡", 2);
            order.put("可乐", 1);
            order.put("薯条", 1);
            
            print(mcSubbranch1);
            System.out.println("------------------------------------------");
            
            //小左开始订餐,直接找mcSubbranch1的这一家分店订餐即可
            mcSubbranch1.handleOrder(new Order(900, 20, order));
            
            System.out.println("------------------------------------------");
            print(mcSubbranch1);
        }
        
        public static void print(Subbranch subbranch){
            if (subbranch == null ) {
                return;
            }
            do {
                if (subbranch instanceof McSubbranch) {
                    System.out.println("[" + subbranch + "]的菜单:" + ((McSubbranch) subbranch).getMenu());
                }
            } while ((subbranch = ((McSubbranch) subbranch).getNextSubbranch()) != null);
        }
        
    }
    复制代码

                    “输出结果和刚才是一样的,不过这下我订餐就好办多了,直接找第一家分店订餐就行,至于到最后谁给我送餐,我就不用管了。”

     1、客户端与具体的处理者解耦,客户端只认识一个Hanlder接口,降低了客户端(即请求发送者)与处理者的耦合度。

      2、客户端和处理者都不关心职责链的具体结构,而是交给职责链的创造者(在上述例子当中则是交给了OrderManager),也正因为如此,当在职责链中添加处理者的时候,这对客户端和处理者来说,都是透明的,二者不知道也不必要知道职责链的变化。

  • 相关阅读:
    Go基础系列:流程控制结构
    Go基础系列:数据类型转换(strconv包)
    Go基础系列:简单数据类型
    Go基础系列:常量和变量
    Go基础系列:map类型
    Go基础系列:Go slice详解
    go基础系列:数组
    Go基础系列:import导包和初始化阶段
    Go基础系列:构建go程序
    go基础系列:结构struct
  • 原文地址:https://www.cnblogs.com/lgg20/p/11101225.html
Copyright © 2011-2022 走看看