Статьи

Шаблоны проектирования: шаблон командования

Рассмотрев несколько шаблонов креационного и структурного проектирования, мы начали паттерны поведения. Вы можете увидеть первую статью в этой категории шаблона стратегии. С помощью шаблонов создания мы узнали, как мы должны создавать наши объекты, и из структурных шаблонов мы узнали, как мы должны структурировать наши классы и объекты, чтобы помочь создать лучшее приложение.

В этой статье мы рассмотрим шаблон проектирования команд. Как следует из названия, в этом паттерне мы будем иметь дело с выполнением различных команд. Позвольте мне рассказать об этом паттерне из Википедии:

Шаблон команды — это шаблон поведенческого проектирования, в котором объект используется для представления и инкапсуляции всей информации, необходимой для вызова метода в более позднее время. Эта информация включает имя метода, объект, которому принадлежит метод, и значения параметров метода.

В основном шаблон имеет множество элементов, как показано ниже. В следующем разделе мы будем исследовать каждый элемент с примером кода. Я буду брать пример с действиями по радио — самые основные действия будут включать или выключать радио. Итак, давайте погрузимся в каждый элемент.

Этот элемент содержит фактическую реализацию (знает, как выполнить запрошенную команду) любых команд. Это также поддерживает историю выполненных команд, но не является частью фактического шаблона команды. Мы увидим эту часть в шаблоне дизайна Memento.

01
02
03
04
05
06
07
08
09
10
11
// Receiver
class radioControl {
    public function turnOn() {
        // Turning On Radio
        echo «Turning On Radio»;
    }
    public function turnOff() {
        // Turning Off Radio
        echo «Turning Off Radio»;
    }
}

Этот элемент содержит информацию о необходимых действиях. Вызывает требуемый метод из receiver .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// Command
interface radioCommand {
    public function execute();
}
 
class turnOnRadio implements radioCommand {
    private $radioControl;
    public function __construct(radioControl $radioControl) {
        $this->radioControl = $radioControl;
    }
    public function execute() {
        $this->radioControl->turnOn ();
    }
}
 
class turnOffRadio implements radioCommand {
    private $radioControl;
    public function __construct(radioControl $radioControl) {
        $this->radioControl = $radioControl;
    }
    public function execute() {
        $this->radioControl->turnOff ();
    }
}

Этот элемент действительно ведет себя как клиент (решая, что делать). Его задача — определить, какую команду выполнить, не зная, кто ее выполнит и как она будет выполнена. В этом примере я воспринял команду как жестко запрограммированное значение, но ее также можно получить из любого места, например, из URL-адреса и / или переменной post.

1
2
// Client
$in = ‘turnOffRadio’;

Этот элемент инициирует весь процесс. Он принимает аргументы от клиента и вызывает процесс для вызова требуемой команды.

1
2
3
4
5
6
7
8
// Invoker
if (class_exists ( $in )) {
    $command = new $in ( new radioControl () );
} else {
    throw new Exception ( ‘..Command Not Found..’ );
}
 
$command->execute ();

Как только мы выполним эту команду, в качестве выходных данных будет показано «Выключение радио», поскольку клиент вызвал эту команду Дополнительные команды могут быть выполнены таким же образом. Если наше действие было установлено как turnOffRadio , то должно отображаться «Включение радио». Достаточно просто, не правда ли?

Давайте обернем все элементы здесь, чтобы увидеть, как это работает.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
// Receiver
class radioControl {
    public function turnOn() {
        // Turning On Radio
        echo «Turning On Radio»;
    }
    public function turnOff() {
        // Turning Off Radio
        echo «Turning Off Radio»;
    }
}
 
// Command
interface radioCommand {
    public function execute();
}
 
class turnOnRadio implements radioCommand {
    private $radioControl;
    public function __construct(radioControl $radioControl) {
        $this->radioControl = $radioControl;
    }
    public function execute() {
        $this->radioControl->turnOn ();
    }
}
 
class turnOffRadio implements radioCommand {
    private $radioControl;
    public function __construct(radioControl $radioControl) {
        $this->radioControl = $radioControl;
    }
    public function execute() {
        $this->radioControl->turnOff ();
    }
}
 
 
// Client
$in = ‘turnOffRadio’;
 
// Invoker
if (class_exists ( $in )) {
    $command = new $in ( new radioControl () );
} else {
    throw new Exception ( ‘..Command Not Found..’ );
}
 
$command->execute ();

Раньше у нас была только одна частота для воспроизведения по радио, поэтому у нас было только два способа — включить или выключить радио. Но представьте, что со временем у нас будет несколько частот для воспроизведения, что заставит нас добавить два новых метода: tuneUp и tuneDown . Давайте посмотрим, как мы можем добавить их.

Когда мы используем шаблоны проектирования, это позволяет нам вносить изменения или расширять функциональность, не внося никаких изменений в код клиента. Это относится и здесь. Мы собираемся добавить еще две команды, но наш клиентский и вызывающий код останутся без изменений.

Добавление новых команд требует изменений в двух местах. Первый — создать новые команды, которые реализуют наш интерфейс radioCommand , а следующий — определить фактическую реализацию этих команд в приемнике.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
class tuneUpRadio implements radioCommand {
    private $radioControl;
    public function __construct(radioControl $radioControl) {
        $this->radioControl = $radioControl;
    }
    public function execute() {
        $this->radioControl->tuneUp ();
    }
}
 
class tuneDownRadio implements radioCommand {
    private $radioControl;
    public function __construct(radioControl $radioControl) {
        $this->radioControl = $radioControl;
    }
    public function execute() {
        $this->radioControl->tuneDown ();
    }
}

Мы будем добавлять два новых метода в наш класс приемника.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
// Receiver
class radioControl {
    public function turnOn() {
        // Turning On Radio
        echo «Turning On Radio»;
    }
    public function turnOff() {
        // Turning Off Radio
        echo «Turning Off Radio»;
    }
     
    public function tuneUp() {
        // Tuning Up Radio
        echo «Tuning Up Radio»;
    }
     
    public function tuneDown() {
        // Tuning Down Radio
        echo «Tuning Down Radio»;
    }
}

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