Understanding the Chain of Responsibility Design Pattern with a Historical Example
This article introduces the Chain of Responsibility design pattern, explains its motivation through a Qing‑dynasty travel scenario, outlines class design and UML, provides complete Java code examples, demonstrates extensibility, and discusses broader applications in modern software systems.
The article begins by introducing the Chain of Responsibility pattern, a classic object‑oriented design technique used to handle a sequence of tasks where each step can pass the request to the next handler.
To illustrate the concept, a whimsical example is presented: modeling Emperor Qianlong’s south‑bound journey during the Qing dynasty, where provincial officials act as handlers that sequentially serve the emperor.
Design steps identify the main participants—Emperor, PrimeMinister (the coordinator), and various Official subclasses representing provincial officials—and describe their relationships, emphasizing the use of an abstract Official class and a concrete PrimeMinister that maintains an ordered list of handlers.
UML diagram (described in text) shows the inheritance hierarchy and the one‑to‑many association between PrimeMinister and Official, with the Emperor passed as a parameter to each serve method.
@Data
public abstract class Official {
protected String title;
protected abstract void serve(Emperor emperor);
@Override
public String toString() { return title; }
}Concrete officials (e.g., HebeiOfficial, ShandongOfficial) override serve to call emperor.play(this, "place"), where the place varies per province.
public class HebeiOfficial extends Official {
public HebeiOfficial() { this.title = "直隶总督"; }
@Override
protected void serve(Emperor emperor) {
emperor.play(this, "避暑山庄");
}
}The Emperor class is a singleton providing a play method that prints the activity, ensuring only one emperor instance exists.
public class Emperor {
private static final Emperor INSTANCE = new Emperor("乾隆");
private final String name;
private Emperor(String name) { this.name = name; }
public static Emperor getInstance() { return INSTANCE; }
public void play(Official official, String place) {
System.out.println(official.getTitle() + " 安排 " + name + "皇帝游览了: " + place);
}
}The PrimeMinister builds the handler list, obtains the emperor, and iterates through the list, invoking each official’s serve method.
public class PrimeMinister {
private static List<Official> list = new ArrayList<>();
public static void main(String[] args) {
list.add(new HebeiOfficial());
list.add(new ShandongOfficial());
list.add(new JiangsuOfficial());
list.add(new ZhejiangOfficial());
Emperor emperor = Emperor.getInstance();
System.out.println("乾隆下江南!");
start(list, emperor);
}
private static void start(List<Official> officials, Emperor emperor) {
for (Official o : officials) { o.serve(emperor); }
}
}Running the program produces an ordered output showing each province’s service, and the article demonstrates how to insert a new handler (e.g., JinanOfficial) to accommodate a sudden itinerary change, highlighting the pattern’s flexibility.
public class JinanOfficial extends Official {
public JinanOfficial() { title = "济南知府"; }
@Override
protected void serve(Emperor emperor) { emperor.play(this, "大明湖畔"); }
}Finally, the article connects the Chain of Responsibility to real‑world frameworks such as Spring MVC filters, Jenkins pipelines, and workflow engines (Activiti, Netflix Conductor), emphasizing its pervasive role in building extensible, maintainable software.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Full-Stack Internet Architecture
Introducing full-stack Internet architecture technologies centered on Java
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
