Gof23种设计模式(15)——责任链模式(Chain of Responsibility)

2020年8月14日10:21:01 评论 56

1 基础知识

1.1 标准定义

责任链(Chain of Responsibility)模式标准定义:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。

1.2 分析和说明

责任链(Chain of Responsibility)模式属于行为型设计模式。在责任链模式中,各种服务组合或对象由没一个服务或对象对其下家的引用而接起来形成一个整体的系统链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。客户并不知道链上的哪一个对象最终处理这个请求,系统可以在不影响客户端的情况下动态的重新组织链和分配责任。处理者有两个选择:承担责任或者把责任推给下家。一个请求可以最终不被任何接收端对象所接受。职责链可以提高系统的灵活性,通过配置多变的职责链可以完成系统功能的扩充或改变,保证系统的可移植性。

责任链(Chain of Responsibility)模式结构如图1所示,其角色包括抽象处理者(Handler)角色和具体处理者(Concrete Handler)角色。

Gof23种设计模式(15)——责任链模式(Chain of Responsibility)图1 责任链模式结构

 抽象处理者(Handler)角色:定义出一个处理请求的接口。如果需要,接口可以定义出一个方法,以设定和返回对下家的引用。这个角色通常由一个抽象类或者接口实现。图中的聚合关系给出了具体子类对下家的引用,抽象方法handleRequest()规范了子类处理请求的操作。

 具体处理者(Concrete Handler)角色:具体处理者接到请求后,可以选择将请求处理掉,或者将请求传给下家。由于具体处理者持有对下家的引用,因此,如果需要,具体处理者可以访问下家。

2 应用场景举例

比如公司技术部门有几位技术高手,当菜鸟在工作中遇到了问题,于是向这些高手们请教,如果第一位高手能解决问题,那这个过程就结束,否则传递给下一个高手,下一个高手也是同样操作,不能解决问题就再交给下下一位。这样,要么这些高手里其中一个能解决问题,要么这些高手全都不能解决这个问题,这就是责任链模式。用例如图2所示。

Gof23种设计模式(15)——责任链模式(Chain of Responsibility)

图2 责任链模式用例图

在这里可以把AbstractSuperMan抽象类理解为抽象处理者(Handler)角色。SuperManOne类,SuperManTwo类和SuperManThree类是具体处理者(Concrete Handler)角色。其结构类图如图3所示。SuperManOne类,SuperManTwo类和SuperManThree类继承AbstractSuperMan抽象类。AbstractSuperMan抽象类进行自我关联。

Gof23种设计模式(15)——责任链模式(Chain of Responsibility)

图3 责任链模式类图

责任链模式实现顺序图见图4,实现顺序描述:
①基于SuperManOne类创建一个superMan1对象;
②基于SuperManTwo类创建一个superMan2对象;
③基于SuperManThree类创建一个superMan3对象;
④基于PrimaryMan类创建一个primaryMan对象;
⑤调用superMan1对象的setSuccessorSuperMan方法,把superMan2对象设置为superMan1对象的下一个链条;
⑥调用superMan2对象的setSuccessorSuperMan方法,把superMan3对象设置为superMan2对象的下一个链条;
⑦调用superMan3对象的setSuccessorSuperMan方法,把superMan1对象设置为superMan3对象的下一个链条;
⑧给primaryMan对象设置标准答案;
⑨primaryMan对象向superMan1对象请求答案;不能解答后转到superMan2对象,最后转到superMan3对象;
⑩superMan3对象正确回答问题并返回答案。

Gof23种设计模式(15)——责任链模式(Chain of Responsibility)

图4 责任链模式实现顺序图

3.Java的实现程序代码

Java程序实现主要包括AbstractSuperMan抽象类文件,PrimaryMan类文件,SuperManOne类文件,SuperManTwo类文件和SuperManThree类文件等5个文件。其关系如图3所示。下面分别列出这4个文件的程序代码,最后列出测试代码并显示输出结果。

AbstractSuperMan抽象类程序代码清单01所示。

程序代码清单01

public abstract class AbstractSuperMan {

	protected String answer;
	protected AbstractSuperMan successorSuperMan;

	public String getAnswer() {
		return answer;
	}

	public void setAnswer(String answer) {
		this.answer = answer;
	}

	public AbstractSuperMan getSuccessorSuperMan() {
		return successorSuperMan;
	}

	public void setSuccessorSuperMan(AbstractSuperMan successorSuperMan) {
		this.successorSuperMan = successorSuperMan;
	}

	public void answerTheQuestion(PrimaryMan man) {
	}
}

PrimaryMan类程序代码清单02所示。

程序代码清单02

public class PrimaryMan {

	private String thisAnswer;

	public boolean question(String answer) {

		if (thisAnswer.equals(answer)) {
			return true;
		}
		return false;

	}

	public String getThisAnswer() {
		return thisAnswer;
	}

	public void setThisAnswer(String thisAnswer) {
		this.thisAnswer = thisAnswer;
	}

}

SuperManOne类,SuperManTwo类和SuperManThree类继承AbstractSuperMan抽象类,其程序代码清单03所示。

程序代码清单03

public class SuperManOne extends AbstractSuperMan {

	private boolean isAnswer = false;

	public void answerTheQuestion(PrimaryMan man) {

		if (man.question(answer)) {
			System.out.println("SuperManOne回答正确。");
		} else {
			if (isAnswer) {
				System.out.println("大家都不能回答这个问题。");
			} else {
				isAnswer = true;
				if (successorSuperMan != null) {
					System.out.println("SuperManOne不会回答问题,提交下一个。");
					successorSuperMan.answerTheQuestion(man);
				}
			}
		}
	}
}

public class SuperManThree extends AbstractSuperMan {

	private boolean isAnswer = false;

	public void answerTheQuestion(PrimaryMan man) {

		if (man.question(answer)) {
			System.out.println("SuperManThree回答正确。");
		} else {
			if (isAnswer) {
				System.out.println("大家都不能回答这个问题。");
			} else {
				isAnswer = true;
				if (successorSuperMan != null) {
					System.out.println("SuperManThree不会回答问题,提交下一个。");
					successorSuperMan.answerTheQuestion(man);
				}
			}
		}
	}
}

public class SuperManTwo extends AbstractSuperMan {

	private boolean isAnswer = false;

	public void answerTheQuestion(PrimaryMan man) {
		if (man.question(answer)) {
			System.out.println("SuperManTwo回答正确。");
		} else {
			if (isAnswer) {
				System.out.println("大家都不能回答这个问题。");
			} else {
				isAnswer = true;
				if (successorSuperMan != null) {
					System.out.println("SuperManTwo不会回答问题,提交下一个。");
					successorSuperMan.answerTheQuestion(man);
				}
			}
		}
	}
}

责任链模式测试程序的代码清单04如下:

程序代码清单04

public class Client {

	public static void main(String[] args) {

		AbstractSuperMan superMan1 = new SuperManOne();
		AbstractSuperMan superMan2 = new SuperManTwo();
		AbstractSuperMan superMan3 = new SuperManThree();

		// 形成一个闭环的链
		superMan1.setSuccessorSuperMan(superMan2);
		superMan2.setSuccessorSuperMan(superMan3);
		superMan3.setSuccessorSuperMan(superMan1);

		// 设置提问者的问题和答案
		PrimaryMan primaryMan = new PrimaryMan();
		primaryMan.setThisAnswer("ANSWER");

		// 让superMan1能回答这个答案
		// superMan1.setAnswer("ANSWER");

		// 让superMan2能回答这个答案
		// superMan2.setAnswer("ANSWER");

		// 让superMan3能回答这个答案
		superMan3.setAnswer("ANSWER");
		superMan1.answerTheQuestion(primaryMan);
	}
}

责任链模式测试类输出结果如下所示:

SuperManOne不会回答问题,提交下一个。
SuperManTwo不会回答问题,提交下一个。
SuperManThree回答正确。

参考链接

11种行为型模式

Gof23种设计模式(13)——解释器模式(Interpreter)
Gof23种设计模式(14)——模板方法模式(Template Method)
Gof23种设计模式(15)——责任链模式(Chain of Responsibility)
Gof23种设计模式(16)——命令模式(Command)
Gof23种设计模式(17)——迭代器模式(Iterator)
Gof23种设计模式(18)——中介者模式(Mediator)
Gof23种设计模式(19)——备忘录模式(Memento)
Gof23种设计模式(20)——观察者模式(Observer)
Gof23种设计模式(21)——状态模式(State)
Gof23种设计模式(22)——策略模式(Strategy)
Gof23种设计模式(23)——访问者模式(Visitor)
Gof23种设计模式 —— 行为型模式总结和比较

回到总目录Gof23种设计模式(全解析)

(转载自微信公众号:架构设计模式)

素课网
  • 本文由 发表于 2020年8月14日10:21:01
  • 转载请注明:https://www.suketech.com/9279.html
设计模式:面向对象设计的六大原则 - 总结 设计模式

设计模式:面向对象设计的六大原则 – 总结

开闭原则是面向对象设计中最基础的设计原则,它指导我们如何建立稳定灵活的系统。开闭原则可能是设计模式六项原则中定义最模糊的一个了,它只告诉我们对扩展开放,对修改关闭,可是到底如何才能做到对扩展开放,对修...
匿名

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: