Gang of Four Behavioural pattern: Chain of Responsibility
Behavioural Pattern
A way of passing a request between a chain of objects. Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an object handles it.
The chain of responsibility pattern is about a chain of decorators each decorator decorating another decorator. The chain of responsibility pattern accentuates the chaining while the decorator pattern accentuates how a class can decorate another class to provide extra functionality without extending it.
In the chain of responsibility pattern the order that the decorators are chained is considered important while with the decorator pattern it is more about adding extra behaviour to the class and the ordering or the fact that multiple decorators can be chained together is not so important.
The Chain of Responsibility pattern is structurally like a Decorator pattern. It is different only in emphasis. It is behavioural pattern and describes the behaviour of chaining multiple decorators together.
Note that the Chain of Responsibility pattern is popular in Servlet Engines. Servlet Filters can be chained together to work on the request.
As the Chain of Responsibility pattern is in all intense and purposes the same structurally as the Decorator pattern you can look at the code examples in the Decorator pattern:
Note that the Chain of Responsibility pattern is a behavioural pattern. It is equivalent to the structural pattern:
Decorator
We will therefore look at the code for the Decorator pattern instead of duplicating the code.
To get the code for this example:
git clone https://github.com/spotadev/gangoffour.git
In src/main/java navigate to this package:
com.javaspeak.designpatterns.go4.structural.decorator
You can run the code from the main method of:
DecoratorApplication
package com.javaspeak.designpatterns.go4.structural.decorator;
/**
* Text book description:
* <ul>
* "Decorator: Add responsibilities to objects dynamically. Attach additional responsibilities
* to an object dynamically. Decorators provide a flexible alternative to subclassing for
* extending functionality."
* </ul>
* The Decorator pattern is useful when some data needs to be transformed several times by
* different plugable transformers.
* <p>
* A Decorator can transform the data and then call another Decorator it is chained to, to do some
* further processing on the data. When the data has been transformed by all the decorators it
* is returned.
* <p>
* In our example we have 2 decorators. One decorator transforms the text to upper case and the
* other decorator replaces multiple spaces with one space.
* <p>
* Each Decorator (transformer) holds a reference to another Decorator unless it is the last
* Decorator in the chain.
* <p>
* Note that the code for the structural Decorator pattern is the same as the behavioural Chain
* of Responsibility pattern.
*
* @see com.javaspeak.designpatterns.go4.behavioural.chainofresponsibility.ChainOfResponsibilityApplication
*
* @author John Dickerson - 20 February 2020
*/
public class DecoratorApplication {
private Transformer<String> transformer;
public void buildDecorators() {
Transformer<String> removeMultipleSpacesTransformer = new RemoveMultipleSpacesTransformer();
transformer = new TextCapitaliseTransformer();
transformer.addDecoration( removeMultipleSpacesTransformer );
}
public void transform() {
String message = "Hello World!";
System.out.println( this.transformer.transform( message ) );
}
public static void main( String[] args ) {
DecoratorApplication application = new DecoratorApplication();
application.buildDecorators();
application.transform();
}
}
package com.javaspeak.designpatterns.go4.structural.decorator;
/**
* This interface is central to this example's Decorator pattern. This Transformer (Decorator) has
* a transform method which can transform data of type E.
* <p>
* The implementation of this Transformer interface can optionally decorate another Transformer.
* <p>
* What the decoration means is that the implementation of the transform( E input ) method should
* do its transformation on E and then if a Transformer has been previously added via its
* addDecoration( Transformer transformer ) method then it should call the transform( E input )
* method of that transformer.
* <p>
* This allows many Decorators to be chained together, each Decorator holding a reference to
* (decorating) the next Decorator. The last Decorator in the chain will not hold a reference to
* another Decorator.
*
* @author John Dickerson - 20 February 2020
*/
public interface Transformer<E> {
/**
* The implementation of this method should perform a transformation on the input. If the
* Transformer holds a reference to another Transformer it should then call transform( E input )
* on the Transformer.
*
* @param input
* The input data to transform
*
* @return data
* The transformed data
*/
public E transform( E input );
/**
* The implementation of this method needs to add a reference to the next transformer in
* the chain.
*
* @param transformer
* The next transformer in the chain.
*/
public void addDecoration( Transformer<E> transformer );
}
package com.javaspeak.designpatterns.go4.structural.decorator;
/**
* This class is a Decorator. It holds a reference to another decorator. The decorators implement
* Transformer. The reference to another decorator can be added by calling
* addDecoration( Transformer<String> transformer).
* <p>
* After calling transform on some input data it calls transform on the decorator it references.
* <p>
* In this way a chain of decorators (transformers) is created, the last transformer in the chain
* holding no reference to a decorator.
*
* @author John Dickerson - 20 February 2020
*/
public class TextCapitaliseTransformer implements Transformer<String> {
private Transformer<String> transformer;
@Override
public void addDecoration( Transformer<String> transformer ) {
this.transformer = transformer;
}
@Override
public String transform( String input ) {
String output = input.toUpperCase();
if ( this.transformer != null ) {
return this.transformer.transform( output );
}
return output;
}
}
package com.javaspeak.designpatterns.go4.structural.decorator;
/**
* This class is a Decorator. It holds a reference to another decorator. The decorators implement
* Transformer. The reference to another decorator can be added by calling
* addDecoration( Transformer<String> transformer).
* <p>
* After calling transform on some input data it calls transform on the decorator it references.
* <p>
* In this way a chain of decorators (transformers) is created, the last transformer in the chain
* holding no reference to a decorator.
*
* @author John Dickerson - 20 February 2020
*/
public class RemoveMultipleSpacesTransformer implements Transformer<String> {
private Transformer<String> transformer;
@Override
public void addDecoration( Transformer<String> transformer ) {
this.transformer = transformer;
}
@Override
public String transform( String input ) {
String output = input.replaceAll( "\\s+", " " );
if ( this.transformer != null ) {
return this.transform( output );
}
return output;
}
}
Back: Gang of Four
Page Author: JD