击鼓传花,层层审批,解决各种 if else 判断的复杂业务情况
责任链模式
概述
使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链发送该请求,直到有一个对象处理它为止。
通常情况下每个接受者包含对另一个接收者的引用,意思就是这个接受者处理不了了,扔给下个人处理,或者这个人处理过了,给下一个人审批。
责任链就是一条链路,传入一个参数,按照事先排好的链路顺序,依次判断处理。
使用场景
有多个对象处理同一个请求的情况,具体哪个对象处理由运行时刻决定(可以理解为需要多次的 if 判断才能决定走哪个分支)
为什么要用责任链模式?直接用 if 判断不行吗?
简单情况下,确实没必要用责任链模式,但是如果 if 判断很多种情况,而且每个分支里处理的代码也有很多呢?必然会难以维护
这种情况责任链就是把每个分支抽出来一个文件,代码逻辑会清晰很多,而且先后处理顺序也是可以自定义的。
优缺点
- 优点:
- 降低耦合度。它将请求的发送者和接收者解耦。
- 简化了对象。使得对象不需要知道链的结构。
- 增强给对象指派职责的灵活性。通过改变链内的成员或者调动它们的次序,允许动态地新增或者删除责任。
- 增加新的请求处理类很方便。
- 缺点:
- 不能保证请求一定被接收(可能所有对象都无法处理此请求)
- 写代码时不小心会造成循环调用
- 调试不方便,因为多个对象来回跳,没有 if 简单明了
类图
简单实现
场景
现在要实现一个日志记录器,根据传入的参数来判断是打印什么类型的日志
预先准备
传入的参数类型是日志类型的枚举:
1 2 3 4 5 6 7 8
| public enum LoggerType { INFO, DEBUG, ERROR }
|
不用设计模式的写法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| public class OriginalDemo {
private void logMessage(LoggerType loggerType, String message) { if (loggerType == LoggerType.INFO) { System.out.println("INFO -- " + message); } else if (loggerType == LoggerType.DEBUG) { System.out.println("DEBUG -- " + message); } else if (loggerType == LoggerType.ERROR) { System.out.println("ERROR -- " + message); } else { System.out.println("无法识别日志类型:" + loggerType); } }
public static void main(String[] args) { OriginalDemo originalDemo = new OriginalDemo(); originalDemo.logMessage(LoggerType.INFO, "INFO 日志"); originalDemo.logMessage(LoggerType.DEBUG, "DEBUG 日志"); originalDemo.logMessage(LoggerType.ERROR, "ERROR 日志"); }
}
|
运行结果:
1 2 3
| INFO -- INFO 日志 DEBUG -- DEBUG 日志 ERROR -- ERROR 日志
|
使用责任链模式
整体思路梳理:就是把日志抽象出一个日志打印抽象类,然后三个分支依次继承,里面写自己的日志打印逻辑;日志抽象类中规划了 setNextLogger 的方法,设置下家,然后定义了 logMessage 方法,来供外部调用,然后 logMessage 中就是定义了判断日志类型的逻辑;
日志链顶层抽象类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| public abstract class AbstractLogger {
protected LoggerType loggerType;
protected AbstractLogger nextLogger;
public void setNextLogger(AbstractLogger nextLogger) { this.nextLogger = nextLogger; }
public void logMessage(LoggerType loggerType, String message) { if (loggerType == this.loggerType) { outputMessage(message); } if (nextLogger != null) { nextLogger.logMessage(loggerType, message); } }
abstract protected void outputMessage(String message); }
|
三种类型的日志打印器
1 2 3 4 5 6 7 8 9 10 11
| public class DebugLogger extends AbstractLogger {
public DebugLogger() { this.loggerType = LoggerType.DEBUG; }
@Override protected void outputMessage(String message) { System.out.println("DEBUG -- " + message); } }
|
1 2 3 4 5 6 7 8 9 10 11
| public class ErrorLogger extends AbstractLogger {
public ErrorLogger() { this.loggerType = LoggerType.ERROR; }
@Override protected void outputMessage(String message) { System.out.println("ERROR -- " + message); } }
|
1 2 3 4 5 6 7 8 9 10 11
| public class InfoLogger extends AbstractLogger {
public InfoLogger() { this.loggerType = LoggerType.INFO; }
@Override protected void outputMessage(String message) { System.out.println("INFO -- " + message); } }
|
测试使用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| public class ChainPatternDemo {
private static AbstractLogger getLoggerChain() { InfoLogger infoLogger = new InfoLogger(); DebugLogger debugLogger = new DebugLogger(); ErrorLogger errorLogger = new ErrorLogger(); infoLogger.setNextLogger(debugLogger); debugLogger.setNextLogger(errorLogger); return infoLogger; }
public static void main(String[] args) { AbstractLogger loggerChain = getLoggerChain();
loggerChain.logMessage(LoggerType.INFO, "INFO 日志测试"); loggerChain.logMessage(LoggerType.DEBUG, "DEBUG 日志测试"); loggerChain.logMessage(LoggerType.ERROR, "ERROR 日志测试"); } }
|
输出结果:
1 2 3
| INFO -- INFO 日志测试 DEBUG -- DEBUG 日志测试 ERROR -- ERROR 日志测试
|