2013-12-03 2 views
1

У меня есть следующая диаграмма UML. CurlRequestHandler и KernelRequestHandler являются одновременно реализацией RequestHandlerInterface. Обработчики запросов несут ответственность за обработку определенного объекта Request, все они возвратят тот же объектResponse.Шаблон стратегии или шаблон цепочки ответственности для определения правильного действия

+------------------------+    +-------------------------+ 
    | CurlRequestHandler  |    | KernelRequestHandler | 
    |------------------------|    |-------------------------| 
    |      |    |       | 
    | - handleRequest(Request)    | - handleRequest(Request)| 
    |      |    |       | 
    |      |    |       | 
    |      |    |       | 
    +------------------------+    +-------------------------+ 
      + 
      |            + 
      |            | 
      |  +---------------------------+  | 
      |  | RequestHandlerInterface |  |    +---------------+ 
      +----> |---------------------------| <-----+    |    | 
         |       |      |    | 
         | - handleRequest(Request) |      | CLIENT  | 
         |       |      |    | 
         |       |      +---------------+ 
         |       | 
         |       | 
         +---------------------------+ 

Теперь, чтобы определить, какой обработчик нужно использовать, я следующее, если заявление в client:

if ($mode == "kernel") { 
    $handler = new KernelRequestHandler(); 
} else { 
    $handler = new CurlRequestHandler(); 
} 

$response = $handler->handleRequest($request); 

Теперь проблема, когда мне нужно, чтобы добавить новый обработчик, Мне нужно изменить инструкцию if. Я заглянул в шаблон дизайна Chain of Responsibility, и это, похоже, лучше справляется с этим, но я не уверен.

Какой шаблон дизайна был бы лучшим подходом для этого?

Штеффен

+2

Кажется мне, как вы хотите перестарайтесь шаблоны проектирования. Нет ничего хуже, имо, чем излишне сложный код. Создание экземпляра динамически с использованием строки в качестве имени класса позволит вам инициализировать всю содержащуюся строку без изменения содержимого i/else, если предположить, что класс существует. '$ className = 'реализация'; $ instance = new $ className(); ' – Virus721

+2

Вам просто нужен простой [заводской шаблон] (http://stackoverflow.com/questions/2079902/factory-abstract-factory-and-factory-method) –

+0

Ой, так как при добавлении нового, если это стало проблемой? Однако вы можете просто выполнить команду if (class_exists ($ className = ucfirst ($ mode). RequestHandler, false)) {$ handler = new $ className(); } else {$ handler = new DefaultRequestHandler(); } ', и это позволит избежать многократного использования ifs. – Twisted1919

ответ

4

Что вам нужно реализовать фабричный шаблон проектирования метод для создания обработчиков.

class HandlerFactory { 

    public function make($mode) { 

     switch(strtolower($mode)) { 

      case 'kernel': return new KernelRequestHandler(); 
      case 'curl': return new CurlRequestHandler(); 
     } 

    } 

} 

И, да, вам нужно добавить кейс для каждого нового обработчика, который вы делаете.

PS: Why you shouldn't call your classes 'handler'

+0

Изменение переключателя та же проблема, что и изменение if if – Virus721

+0

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

+2

@ Virus721 Да - Разница заключается в том, что он заключен в заводе – AlexP

1

Если $ режим равен начале вашего RequestHandler класса, то вы можете просто добавить его.

$mode = 'kernel'; 
$class = ucfirst($mode).'RequestHandler'; 
$handler = new $class; 

будет производить new KernelRequestHandler

+0

и несколько ошибок в конечном счете. Возможно, нет. Короткий пробег будет. –

+0

Это не очень хороший подход, на мой взгляд. Но спасибо за то, что поделились своими идеями! –

+0

@ ArlaudPierre какие ошибки? :) –

0
class RequestFactory { 
    public static function getHandler($mode) { 
     $className = ucfirst($mode).'RequestHandler'; 
     return new $className(); 
    } 
} 

Вы можете использовать его как это:

$handler = RequestFactory::getHandler('kernel'); 
$handler->handleRequest($request); 
+0

Почему статический метод? Создать статический конкурс только для того, чтобы избежать создания фабрики? –

+0

Да. Это плохо? –

+0

Имхо, делая это, нарушает ООП. Вы не можете правильно продлить свою фабрику. Это не фабрика, потому что она ничего не создает (это не объект). Я имею в виду, что это эквивалентно глобальному методу getHandler(). Тогда зачем беспокоиться о том, чтобы положить его в класс? Программирование в императивном стиле - это не плохо, но я склонен полагать, что смешивание его с ООП подвержено ошибкам. На самом деле я думаю, что это самая большая жалоба, которую многие люди имели о C++. –

Смежные вопросы