Пример Composite + Chain of Responsibility - PullRequest
2 голосов
/ 16 марта 2010

Может ли кто-нибудь привести практический пример совместного использования шаблонов проектирования Composite и Chain of Responsibility?

Спасибо

Ответы [ 3 ]

3 голосов
/ 03 августа 2016

Очень практичным примером является дизайн графического интерфейса, например, с каркасом Qt.

QObject может быть отдельным объектом или составным из большего количества объектов. Объекты QObject (в идеале) знают свой родительский объект QObject, поэтому они также образуют цепь ответственности .

Пример: Главное окно имеет диалог (QObject). Диалог имеет строку ввода и поле макета (все объекты QObject). Окно макета имеет 2 кнопки (все объекты QObject).

Событие для кнопки (например, нажатие) будет передаваться по цепочке ответственности , пока объект QObject не сможет обработать событие.

Другое направление также работает (из-за композитного дизайна). Функция show () для диалогового окна будет передана дочерним объектам, поэтому строка ввода, поле компоновки и кнопки также станут видимыми.

2 голосов
/ 15 января 2018

Этот пример объединяет Цепочка ответственности , Команда и Составной и использует стиль метода Try*, знакомый .NET.

Дано команда и обработчик типы:

public interface IResults { }

public interface ICommand { }

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

С учетом нескольких IHandler реализаций:

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

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

И композит IHandler реализация:

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;
    }
}

И используя его в коде клиента:

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
}

Благодаря использованию обобщений параметризация / ограничения типов также могут обеспечить определенную степень безопасности:

public interface IResults { }

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

public interface IHandler<TCommand, TResults>
    where TCommand : ICommand<TResults>
    where TResults : IResults
{
    // ...
}
2 голосов
/ 16 марта 2010

Практический ответ может быть невозможен, но я вижу, где у вас будет структура цепей ответственности. Вот пример на питоне:

>>> 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)

Таким образом, объект SomeSystem представляет собой совокупность performance_monitor и exception_monitor. Каждый из композитов вернет серию обработчиков для желаемой цепи ответственности. Хотя этот пример действительно только усложняет более простые цепочки ответственности, где SomeSystem может быть инициирована с помощью самих цепочек. Хотя хранение их в упаковке может быть полезным.

...