设计模式-使用责任链模式改造if else


在这里插入图片描述

简介

普通的 if else 或者 switch case 语句虽然可以做选择,但是一旦条件增加,就显得混乱。责任链模式的的思想其实和 if else 或者 switch case 很类似都是一步步做过滤,只不过责任链是通过对象来过滤罢了,责任链可以看做一条单链表的数据结构,一个对象一个对象的过滤条件,符合的就执行然后结束,不符合的就往后传递,如果每个对象都无法处理,一般会有一个最终的处理器来处理

代码实现

我们先看故事场景

假如你朋友有一辆豪车,但是它坏掉了,朋友委托你帮他找原厂家修理,可是你是一个车盲,不知道这是哪个牌子的车,可能是宾利,劳斯莱斯,兰博基尼?你只能一家家的打电话询问

// 处理请求的责任链结点
public abstract class Handler {
    // 后继结点
    public Handler successor;
    
    // 如何处理请求
    public abstract void handlerRequest(String car);
    
    // set successor
    public void setSuccessor(Handler successor) {
        this.successor = successor;
    }
}

// 宾利 Handler 1
public class BentleyHandler extends Handler {
    @Override
    public void handlerRequest(String car) {
        if (car.equals("宾利")) {
            System.out.println("这里是宾利公司,可以修理宾利汽车");
        }
        else {
            successor.handlerRequest(car);
        }
    }
}

// 劳斯莱斯 Handler 2
public class RollsRoyceHandler extends Handler {
    @Override
    public void handlerRequest(String car) {
        if (car.equals("劳斯莱斯")) {
            System.out.println("这里是劳斯莱斯公司,可以修理劳斯莱斯汽车");
        }
        else {
            successor.handlerRequest(car);
        }
    }
    
}

// 兰博基尼 Handler 3
public class LamborghiniHandler extends Handler {
    @Override
    public void handlerRequest(String car) {
        if (car.equals("兰博基尼")) {
            System.out.println("这里是兰博基尼公司,可以修理兰博基尼汽车");
        }
        else {
            successor.handlerRequest(car);
        }
    }
}

// 终极处理器 Handler 4
public class OthersHandler extends Handler {
    @Override
    public void handlerRequest(String car) {
        System.out.println("不知道汽车类型,还没有公司能处理这款车");
    }
}

// 主函数入口
public class Demo {
    public static void main(String[] args) {
        // 责任链中的各个对象
        Handler bentley = new BentleyHandler();
        Handler rollsRoyce = new RollsRoyceHandler();
        Handler lamborghini = new LamborghiniHandler();
        Handler others = new OthersHandler();
        
        // 构建一条责任链(创建单链表)
        bentley.setSuccessor(rollsRoyce);
        rollsRoyce.setSuccessor(lamborghini);
        lamborghini.setSuccessor(others);
        
        // 通过责任链一家家的排查,宾利->劳斯莱斯->兰博基尼,最终找到车型!
        String car = "兰博基尼";
        Bentley.handlerRequest(car);
    }
}

优缺点

责任链模式优点

  • 可以将请求的发送者和接受者进行解耦
  • 通过改变 handler 的连接顺序来进行次序调动,甚至可以删除

责任链模式缺点

  • 不是很容易观察运行时的特点,造成难以找错误

应用场景

使用场景

  • 比如窗口系统中,处理鼠标或者键盘的事件
  • SpringMVC 的 DispatcherServlet 就是使用了责任链

改进责任链

标准的责任链我们可以看见上面的示例,最明显的特征就是解耦了各个判断的对象,要改哪个判断语句我们可以直接在那个对象中去修改,不用再去关注繁杂的 if else 或者 switch case 了,但是传统的责任链依然有一些麻烦的地方

麻烦点:

  • Handler 中的handlerRequest()方法往往不是一个,可能有多个
  • bentley.handlerRequest(car)这样的写法有不好的地方,万一 Bentley 这个类被我们删掉了怎么办,又要去改这一行代码吗?我们能去设置一个责任链的头结点吗?
  • 如果 handlerRequest() 方法有多个,同时我们假如有个 head 头结点,那么开始遍历责任链我们应该让 head 调用哪一个 handlerRequest() 方法呢?或者专门设置一个start()?还有如果我们想从责任链中任意一个结点开始遍历呢?
  • 责任链上各个结点调用setSuccessor()来组成完整的链表,但是万一哪个对象我们不需要了,则代码我们需要重新串起来,有些麻烦,有简单的方法不去重新 set,比如说直接删除就行?

基于上面这些考虑我们改进了一下责任链,现在我们再来看一下代码

// 处理请求的责任链结点
public abstract class Handler {
    // 后继结点
    public Handler successor;

	// 责任链
	public void start(String car, String status) {
		if (status.equals("退货")) {
			handlerRequest1(car);
		}
		else if (status.equals("维修")) {
			handlerRequest2(car);
		}
		else {
			System.out.println("没有什么需求请不要打电话骚扰客服!");
		}
	}
    
    // 退货处理请求 1
    public abstract void handlerRequest1(String car);

	// 维修处理请求 2
	public abstract void handlerRequest2(String car);
    
    // set successor
    public Handler setSuccessor(Handler successor) {
        this.successor = successor;
    }
}

// 头结点
public class HeadHandler extends Handler {
	@Override
    public void handlerRequest1(String car) {
        successor.handlerRequest1(car);
    }
	@Override
    public void handlerRequest2(String car) {
        successor.handlerRequest2(car);
    }
}

// 宾利 Handler 1
public class BentleyHandler extends Handler {
	@Override
    public void handlerRequest1(String car) {
        if (car.equals("宾利")) {
            System.out.println("这里是宾利公司,可以接收宾利汽车退货");
        }
        else {
            successor.handlerRequest1(car);
        }
    }
    @Override
    public void handlerRequest2(String car) {
        if (car.equals("宾利")) {
            System.out.println("这里是宾利公司,可以修理宾利汽车");
        }
        else {
            successor.handlerRequest2(car);
        }
    }
}

// 劳斯莱斯 Handler 2
public class RollsRoyceHandler extends Handler {
	@Override
    public void handlerRequest1(String car) {
        if (car.equals("劳斯莱斯")) {
            System.out.println("这里是劳斯莱斯公司,可以接收劳斯莱斯汽车退货");
        }
        else {
            successor.handlerRequest1(car);
        }
    }
    @Override
    public void handlerRequest2(String car) {
        if (car.equals("劳斯莱斯")) {
            System.out.println("这里是劳斯莱斯公司,可以修理劳斯莱斯汽车");
        }
        else {
            successor.handlerRequest2(car);
        }
    }
    
}

// 兰博基尼 Handler 3
public class LamborghiniHandler extends Handler {
	@Override
    public void handlerRequest1(String car) {
        if (car.equals("兰博基尼")) {
            System.out.println("这里是兰博基尼公司,可以接收兰博基尼汽车退货");
        }
        else {
            successor.handlerRequest1(car);
        }
    }
    @Override
    public void handlerRequest2(String car) {
        if (car.equals("兰博基尼")) {
            System.out.println("这里是兰博基尼公司,可以修理兰博基尼汽车");
        }
        else {
            successor.handlerRequest2(car);
        }
    }
}

// 尾结点(终极处理器)
public class TailHandler extends Handler {
	@Override
    public void handlerRequest1(String car) {
        System.out.println("不知道汽车类型,还没有公司能处理此车退货");
    }
    @Override
    public void handlerRequest2(String car) {
        System.out.println("不知道汽车类型,还没有公司能处理此车维修");
    }
}

// 主函数入口
public class Demo {
    public static void main(String[] args) {
        // 责任链中的各个对象
        Handler head = new HeadHandler();
        Handler bentley = new BentleyHandler();
        Handler rollsRoyce = new RollsRoyceHandler();
        Handler lamborghini = new LamborghiniHandler();
        Handler tail = new TailHandler();
        
        // 构建一条完整责任链(创建单链表)
        head.setSuccessor(bentley).setSuccessor(rollsRoyce).setSuccessor(lamborghini).setSuccessor(tail);
        
        // 通过责任链一家家的排查,宾利->劳斯莱斯->兰博基尼,最终找到车型!
        String car = "兰博基尼";
        String status = "维修";
        head.start(car, status);
    }
}

我们再来看一些这个 demo 优势就显而易见了,它可以通过 head.start() 的方式启动责任链,而不需要通过指定某一个 handlerRequest 方法来启动,并且即使 BentleyHandler 被我们删除,也无需修改head.start(),还有一个好处,那就是由于 start 方法作为抽象类 handler 的非抽象方法,意味着,我们可以在责任链任意一个结点调用 start 都可以正常的遍历责任链

我们还可以发现setSuccessor()方法有返回值,这样我们可以连续不断的 setSuccessor,即使中间有某一种 Handler 被我们剔除我们可以直接删除个 setSuccessor 方法,而不是像之前一样还要考虑修改代码时候承上启下的 handler 之间的关系

猜你喜欢

转载自blog.csdn.net/abcnull/article/details/107565909