From 2667840060a6375c716d336c2c5f3aad6eb7c3f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilkka=20Sepp=C3=A4l=C3=A4?= Date: Sun, 24 Mar 2024 11:16:29 +0200 Subject: [PATCH] docs: Improve Chain of Responsibility docs --- chain-of-responsibility/README.md | 56 +++++++++++++++---- .../main/java/com/iluwatar/chain/Request.java | 30 +--------- 2 files changed, 47 insertions(+), 39 deletions(-) diff --git a/chain-of-responsibility/README.md b/chain-of-responsibility/README.md index e9ed08631..175143491 100644 --- a/chain-of-responsibility/README.md +++ b/chain-of-responsibility/README.md @@ -3,9 +3,16 @@ title: Chain of responsibility category: Behavioral language: en tag: - - Gang of Four + - Gang of Four + - Decoupling --- +## Also known as + +* Chain of Command +* Chain of Objects +* Responsibility Chain + ## Intent Avoid coupling the sender of a request to its receiver by giving more than one object a chance to @@ -36,6 +43,9 @@ Wikipedia says Translating our example with the orcs from above. First, we have the `Request` class: ```java +import lombok.Getter; + +@Getter public class Request { private final RequestType requestType; @@ -46,17 +56,15 @@ public class Request { this.requestType = Objects.requireNonNull(requestType); this.requestDescription = Objects.requireNonNull(requestDescription); } - - public String getRequestDescription() { return requestDescription; } - - public RequestType getRequestType() { return requestType; } - - public void markHandled() { this.handled = true; } - - public boolean isHandled() { return this.handled; } - + + public void markHandled() { + this.handled = true; + } + @Override - public String toString() { return getRequestDescription(); } + public String toString() { + return getRequestDescription(); + } } public enum RequestType { @@ -163,11 +171,37 @@ Use Chain of Responsibility when ## Known uses +* Event bubbling in GUI frameworks where an event might be handled at multiple levels of a UI component hierarchy +* Middleware frameworks where a request passes through a chain of processing objects +* Logging frameworks where messages can be passed through a series of loggers, each possibly handling them differently * [java.util.logging.Logger#log()](http://docs.oracle.com/javase/8/docs/api/java/util/logging/Logger.html#log%28java.util.logging.Level,%20java.lang.String%29) * [Apache Commons Chain](https://commons.apache.org/proper/commons-chain/index.html) * [javax.servlet.Filter#doFilter()](http://docs.oracle.com/javaee/7/api/javax/servlet/Filter.html#doFilter-javax.servlet.ServletRequest-javax.servlet.ServletResponse-javax.servlet.FilterChain-) +## Consequences + +Benefits: + +* Reduced coupling. The sender of a request does not need to know the concrete handler that will process the request. +* Increased flexibility in assigning responsibilities to objects. You can add or change responsibilities for handling a request by changing the members and order of the chain. +* Allows you to set a default handler if no concrete handler can handle the request. + +Trade-Offs: + +* It can be challenging to debug and understand the flow, especially if the chain is long and complex. +* The request might end up unhandled if the chain doesn't include a catch-all handler. +* Performance concerns might arise due to potentially going through several handlers before finding the right one, or not finding it at all. + +## Related Patterns + +[Command](https://java-design-patterns.com/patterns/command/): can be used to encapsulate a request as an object, which might be passed along the chain. +[Composite](https://java-design-patterns.com/patterns/composite/): the Chain of Responsibility is often applied in conjunction with the Composite pattern. +[Decorator](https://java-design-patterns.com/patterns/decorator/): decorators can be chained in a similar manner as responsibilities in the Chain of Responsibility pattern. + ## Credits * [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59) * [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b) +* [Pattern-Oriented Software Architecture, Volume 1: A System of Patterns](https://amzn.to/3PAJUg5) +* [Refactoring to Patterns](https://amzn.to/3VOO4F5) +* [Pattern languages of program design 3](https://amzn.to/4a4NxTH) diff --git a/chain-of-responsibility/src/main/java/com/iluwatar/chain/Request.java b/chain-of-responsibility/src/main/java/com/iluwatar/chain/Request.java index 621938fd3..05c0d88d5 100644 --- a/chain-of-responsibility/src/main/java/com/iluwatar/chain/Request.java +++ b/chain-of-responsibility/src/main/java/com/iluwatar/chain/Request.java @@ -25,10 +25,12 @@ package com.iluwatar.chain; import java.util.Objects; +import lombok.Getter; /** * Request. */ +@Getter public class Request { /** @@ -59,25 +61,6 @@ public class Request { this.requestDescription = Objects.requireNonNull(requestDescription); } - /** - * Get a description of the request. - * - * @return A human readable description of the request - */ - public String getRequestDescription() { - return requestDescription; - } - - /** - * Get the type of this request, used by each person in the chain of command to see if they should - * or can handle this particular request. - * - * @return The request type - */ - public RequestType getRequestType() { - return requestType; - } - /** * Mark the request as handled. */ @@ -85,15 +68,6 @@ public class Request { this.handled = true; } - /** - * Indicates if this request is handled or not. - * - * @return true when the request is handled, false if not - */ - public boolean isHandled() { - return this.handled; - } - @Override public String toString() { return getRequestDescription();