4

Can anyone give a practical example of using the design patterns Composite and Chain of Responsibility together?

Thanks

Fabio
  • 3,020
  • 4
  • 39
  • 62

3 Answers3

4

A very practical example is GUI design, for example with the Qt framework.

A QObject can be an individual object or a composite of more objects. QObjects (ideally) know their parent QObject, so they also form a chain of responsibility.

Example: The main window has a dialog (a QObject). The dialog has an input line and a layout-box (all QObjects). The layout box has 2 buttons (all QObjects).

An event to a button (e.g. click) will be passed on through the chain of responsibility until an QObject can handle the event.

The other direction also works (due to the composite design). A show() to the dialog will be passed to the child-objects, so the input-line and the layout-box and the buttons will become visible too.

Sascha
  • 986
  • 10
  • 30
4

This example combines Chain of Responsibility, Command, and Composite, and leverages the Try* method style familiar to .NET.

Given command and handler types:

public interface IResults { }

public interface ICommand { }

public interface IHandler
{
    Boolean TryHandle(ICommand command, out IResults results);
}

Given a few IHandler implementations:

public class FooHandler : IHandler
{
    public Boolean TryHandle(ICommand command, out IResults results)
    {
        // ...
    }
}

public class BarHandler : IHandler
{
    public Boolean TryHandle(ICommand command, out IResults results)
    {
        // ...
    }
}

And a composite IHandler implementation:

public class CompositeHandler : IHandler
{
    public IList<IHandler> Handlers { get; } = new List<IHandler>();

    public Boolean TryHandle(ICommand command, out IResults results)
    {
        foreach (var handler in this.Handlers) {
            if (handler.TryHandle(command, out results)) {
                return true;
            }
        }
        results = null;
        return false;
    }
}

And using it in client code:

var command = /* ... */;

var handler = new CompositeHandler();
handler.Handlers.Add(new FooHandler());
handler.Handlers.Add(new BarHandler());

IResults results;
if (handler.TryHandle(command, out results)) {
    // handled
}
else {
    // not handled
}

Through the use of generics, type parameterization/constraints can ensure a degree of safety too:

public interface IResults { }

public interface ICommand<TResults>
    where TResults : IResults
{
    // ...
}

public interface IHandler<TCommand, TResults>
    where TCommand : ICommand<TResults>
    where TResults : IResults
{
    // ...
}
Dan Lugg
  • 20,192
  • 19
  • 110
  • 174
2

A practical answer may be impossible, but I can see where you would have a composition of chains of responsibility. Here's a pythonish example:

>>> class DevelopmentPerformanceMonitor():
...   def getPerformanceMonitorHandlers():
...     return []
... 
>>> class ProductionPerformanceMonitor():
...   def getPerformanceMonitorHandlers():
...     return [check_cpu_under_load, check_available_hd]
... 
>>> class DevelopmentExceptionMonitor():
...   def getExceptionHandlers():
...     return [email_local_root, log_exception]
... 
>>> class ProductionExceptionMonitor():
...   def getExceptionHandlers():
...     return [emails_system_admin, log_exception, create_ticket]
... 
>>> class SomeSystem:
...    pm = None # Performance Monitor
...    em = None # Exception Monitor
...    def __init__(self, performance_monitor, exception_monitor):
...      pm = performance_monitor
...      em = exception_monitor
...    def on_exception(e):
...      for handler in em.getExceptionHandlers():
...        handler(e)
...    def perform_performance_monitoring(s):
...      for handler in pm.getPerformanceMonitorHandlers():
...        handler(s)

So the SomeSystem object is a composite of a performance_monitor and an exception_monitor. Each of the composites will return a series of handlers for desired chain of responsibility. Although this example is really only complicating a simpler Chains of Responsibility, where the SomeSystem could be initiated with the chains themselves. Although keeping them packaged may be helpful.

W Devauld
  • 72
  • 4
  • 1
    I've found a good example of Composite + Chain of Responsibility, in the book "Design Patterns in Java", by Steven Metsker and William Wake. You can read it at Google Books. Basically, we've got machine, lines, bays and factories. Factories are compositions of bays, and so on. At this point, we get the Composite pattern. Each element, from machines to factories, have an engineer who's responsible for the component. But, in some cases, a simple machine doesn't have an engineer, so we've got to look for its parent to find him (CoR). []'s – Fabio Apr 10 '10 at 01:43