2009-03-13 3 views
13

Я столкнулся с шаблоном проектирования, который был назван «Образцом обработчика», но я не могу найти никаких реальных ссылок на этот шаблон нигде. Это в основном просто интерфейс с одним методом, который позволяет вам легко расширять функциональность в фоновом режиме, не перекомпилируя клиентов. Может быть полезно для веб-службы, которая должна обрабатывать множество различных типов запросов. Вот пример:Картина "Handler"?

public interface IHandler 
{ 
    IDictionary<string, string> Handle(IDictionary<string, string> args); 
} 

В арг, как правило, включают в себя один ключ, как «Action» со значением, который говорит implmentation, что делать. Дополнительные аргументы могут быть переданы, чтобы дать им больше информации. Затем impl затем возвращает произвольный список аргументов, которые клиент должен «понять».

Является ли это анти-шаблоном или, возможно, еще одним шаблоном в маскировке? Рекомендуется ли этот тип дизайна?

EDIT: Немного больше информации: Как я видел это реализовано, «корневой» обработчик будет действовать как диспетчер для других конкретных обработчиков (может быть?). Корневой обработчик имеет «HandlerResolver», который решает, какой конкретный обработчик должен получить сообщение на основе его содержимого. Возможно, это на самом деле похоже на образец «диспетчера», хотя я не знаю, действительно ли это шаблон. Я предполагаю, что он также может иметь шаблон цепочки ответственности в корне, который позволяет вам объединить кучу конкретных обработчиков, а затем позволить им решить, какой из них будет обрабатывать.

ответ

9

это ООП способ сделать затворов на языках, которые не имеют их. у него не было имени «шаблона», потому что на функциональных языках это очевидный способ работы. на языках ООП, OTOH, вам нужно сделать какую-то работу, поэтому она кажется именованной идиомой. «Обработчик» звучит правильно.

(это не синглтон, BTW)

1

Я не знаю, действительно ли это рекомендуется, но я действительно должен был использовать этот тип шаблона в некоторых приложениях MATLAB, которые я написал, чтобы имитировать ссылочное поведение для объектов (теперь это ненужно с более новыми версиями).

По иронии судьбы, я фактически назвал функцию «обработчик». Мой объект просто сохранил одно поле, содержащее ссылку на дескриптор функции (@handler), и методы были просто оболочками, которые вызывали эту функцию. Например, перегруженная функция GET для объекта будет просто позвонить:

object.handler('get',...input argument list...) 

Я не уверен, если это считается «хорошим» выбором дизайна на других языках. Я выбрал это по необходимости, потому что это был единственный способ, которым я столкнулся, чтобы создать подобное поведение в MATLAB (функция обработчика имела доступ к рабочему пространству инициализированных данных, которое мне не нужно было бы пропускать и выходить из различных вызовы методов). В новейших версиях MATLAB теперь есть класс HANDLE, который может сделать этот материал намного более чистым способом.

2

Я использую его под именем «SingletonRegistry»

См this thread

Я использовать его пару раз. Специально, когда действия, которые необходимо предпринять, неизвестны заранее (на первых этапах проектирования) или приложение должно поддерживать экстремальную гибкость.

Я загружаю словарь либо из файла, либо из базы данных и создаю один экземпляр класса, который будет обрабатывать запрос под определенным «ключом».

Я нашел это class also, ища в Интернете для этого имени.

Похоже, что это не так?

2

Поскольку у вас было слово «действие» в вашем посте, я убежден, что это может быть частью шаблона Command. Проверьте Wiki и найдите «Handler» ... возможно, это даст немного больше понимания.

http://en.wikipedia.org/wiki/Command_pattern

+0

Да, командная модель была моей первой догадкой о том, что это было. Я думаю, что команда типа использует нечто подобное этому внутренне с помощью метода «Выполнение». –

1

Я думаю, что цель избежать перекомпиляций гораздо лучше обслуживаться COM под влиянием дизайна. Какие дополнительные гибкость вы получите от этого:

IHandler UserHandler = ...; 

Dictionary<string,string> result = UserHandler.Handle(
    new Dictionary<string, string>{ 
     { "Action", "AddUser" }, 
     { "UserName", "Joe Bloggs" }, 
     { "Age", "23" } }); 
NewUserId = Int.Parse(result["UserId"]); 

над:

IUserHandler UserHandler = ...; 

AddUserResult result = UserHandler.AddUser(new AddUserArgs { 
    UserName = "Joe Bloggs", 
    Age = 23 }); 
NewUserId = result.UserId; 

, когда вы можете расширить действия, результаты и аргументы:

IUserHandler UserHandler = ...; 

AddUserResult2 result = UserHandler.AddUser(new AddUserArgs2 { 
    UserName = "Joe Bloggs", 
    Age = 23, 
    Password = "xyzzy" }); 
NewUserId = result.UserId; 
SessionId = result.SessionId; 

IUserHandler2 UserHandler2 = UserHandler as IUserHandler2; 
if (UserHandler2 != null) 
{ 
    LoginUserResult loginResult = UserHandler2.LoginUser(new LoginUserArgs { 
     UserId = NewUserId, 
     SessionId = SessionId, 
     Password = "xyzzy" }); 
} 
+0

Я предполагаю, что только дополнительная гибкость, которую вы получаете с помощью «Handle», заключается в том, что вам даже не нужен конкретный метод на интерфейсе, например «AddUser» или «LoginUser». С ручкой вы получаете бесконечную гибкость в отношении того, что может сделать интерфейс, за счет удобства использования. –

+0

Вот почему у меня был пример IUserHandler2, показывающий, что вы можете добавлять новые действия. Это немного больше подробностей, но я предпочитаю открытость и четкую обратную связь о том, какая версия доступна. Кроме того, вы можете проверить доступность метода при подключении. –

+0

Я согласен, метод «ручка» определенно отстой для обнаружения –

0

Я видел " Handler "в старых базовых кодах, особенно для веб-служб. Из того, что я видел, они обычно оказываются адаптером, фасадом или некоторым подобным шаблоном и в конечном итоге получают вызов обработчика, поскольку он обрабатывает запрос.