A couple of months ago, I applied the Chain of Responsibility pattern for the very first time. I've never encountered a scenario before where applying this pattern would be a valid option. But now, after some refactoring, I somehow naturally ended up applying this rarely used design pattern. Lets dive into some code, shall we?
public interface IProcessor
{
IProcessor Successor
{ get; set; }
void Process(Request request);
}
public abstract class BaseProcessor : IProcessor
{
public IProcessor Successor { get; set; }
public void Process(Request request)
{
// Some base class behaviour
FurtherProcess(request);
if(null != Successor)
{
Successor.Process(request);
}
}
protected abstract void FurtherProcess(Request request);
}
This is the base class for all processor classes (bad naming, huh?) . If there is a follow-up processor available, then its Process method is called. The processor classes can now focus on their main responsibility:
public class Processor1 : BaseProcessor
{
protected override void FurtherProcess(Request request)
{
// Do something usefull
}
}
I'm using Castle Windsor to chain together the different processors in the particular order that I want. This involves setter injection for the Successor property. Although I'm not a huge fan of setter injection, in this case it seems like a viable option. The following example uses the fluent interface of Castle Windsor for configuring the container:
_container.Register(
Component.For<ProcessorConsumer1>()
.Named("ProcessorConsumer1")
.Parameters(Parameter.ForKey("processor")
.Eq("${Processor1}")),
Component.For<IProcessor>()
.Named("Processor1")
.ImplementedBy<Processor1>()
.Parameters(Parameter.ForKey("Successor")
.Eq("${Processor2}")),
Component.For<IProcessor>()
.Named("Processor2")
.ImplementedBy<Processor2>());
Nothing much to it. The ProcessConsumer class simply gets the first processor injected through its constructor. The above configuration results in the following chain:
ProcessConsumer1 -> Processor1 -> Processor2
Everything is fine and dandy so far. Now suppose that I want to add another ProcessConsumer that requires a slightly enhanced chain of processors like so:
ProcessConsumer1 -> Processor1 -> Processor2
ProcessConsumer2 -> Processor3 -> Processor1 -> Processor2
This is how the configuration of Castle Windsor now looks like:
_container.Register(
Component.For<ProcessorConsumer1>()
.Named("ProcessorConsumer1")
.Parameters(Parameter.ForKey("processor")
.Eq("${Processor1}")),
Component.For<ProcessorConsumer2>()
.Named("ProcessorConsumer2")
.Parameters(Parameter.ForKey("processor")
.Eq("${Processor3}")),
Component.For<IProcessor>()
.Named("Processor1")
.ImplementedBy<Processor1>()
.Parameters(Parameter.ForKey("Successor")
.Eq("${Processor2}")),
Component.For<IProcessor>()
.Named("Processor2")
.ImplementedBy<Processor2>(),
Component.For<IProcessor>()
.Named("Processor3")
.ImplementedBy<Processor3>()
.Parameters(Parameter.ForKey("Successor")
.Eq("${Processor1}")));
With this particular configuration, Castle Windsor now throws an exception with the following description:
A cycle was detected when trying to resolve a dependency.
After some investigation it seems that Castle Windsor wants to set the Successor property of Processor2 with the instance of Processor1, which is not what I had in mind. The Successor property of Processor2 should remain empty. I believe this has something to do with the approach that Castle Windsor is taking to never inject a null reference, although I'm not completely sure.
Anyway, I got around this issue by splitting up the IProcessor interface and the BaseProcessor class as outlined in my next post.