Команда (Command): выбор операции во время выполнения
В книге Advanced C++:Programming Styles And Idioms (Addison-Wesley, 1992), Джим Коплен (Jim Coplien) ввел термин функтор, который является объектом, главнейшим назначением которого является инкапсуляция функций (так как "функтор" имеет математическое значение, в этой книге я буду использовать более явный термин функционный объект). Назначение его состоит в отделении выбора вызываемой функции от места, где функция вызывается.
Этот термин упоминается, но не используется в книге Design Patterns. Однако, тема функционных объектов повторяется в нескольких шаблонах этой книги.
Команда (Command)- это функционный объект в чистом виде: метод, который является объектом. [7] При упаковывании метода в объект вы можете передать его в другой метод или объект в качестве параметра, чтобы попросить его выполнить определенную операцию в процессе выполнения вашего запроса. Вы можете сказать, что Command является посыльным (поскольку он предназначен и используется достаточно прямолинейно), который переносит поведение, а не данные.
//: command:CommandPattern.java
package command;
import java.util.*;
import junit.framework.*;
interface Command {
void execute();
}
class Hello implements Command {
public void execute() {
System.out.print("Hello ");
}
}
class World implements Command {
public void execute() {
System.out.print("World! ");
}
}
class IAm implements Command {
public void execute() {
System.out.print("I'm the command pattern!");
}
}
// Объект, который хранит команды:
class Macro {
private List commands = new ArrayList();
public void add(Command c) {
commands.add(c);
}
public void run() {
Iterator it = commands.iterator();
while (it.hasNext())
((Command) it.next()).execute();
}
}
public class CommandPattern extends TestCase {
Macro macro = new Macro();
public void test() {
macro.add(new Hello());
macro.add(new World());
macro.add(new IAm());
macro.run();
}
public static void main(String args[]) {
junit.textui.TestRunner.run(CommandPattern.class);
}
} // /:~
Основное назначение Command состоит в предоставлении вам желаемого действия в методе или объекте. В приведенном выше примере она предоставляет способ для очереди действий, выполняемых коллективно. В этом случае шаблон позволяет вам динамически создать новое поведение, которое обычно вы можете сделать только при написании нового кода, но в приведенном выше примере может быть сделано при интерпретировании скрипта (смотрите шаблон Интерпретатор, если хотите получить большую сложность).
Другим примером Command является refractor: DirList.java [????]. Класс DirFilter является объектом команды, который содержит действие в методе accept( ), который передается в метод list( ). Метод list( ) определяет, что включать в результат, вызывая метод accept( ).
В книге Design Patterns говорится, что "Команды являются объектно-ориентированной заменой для обратного вызова [8]". Однако, я думаю, что слово "обратный" является существенной частью концепции обратных вызовов. Таким образом, я думаю, обратный вызов возвращается назад к создателю обратного вызова. С другой стороны, объект Command вы обычно создаете и передаете в некоторый метод или объект, и никак иначе не привязываетесь к объекту Command. Такой мой взгляд на этот предмет. Далее в этой книге я собрал группу шаблонов проектирования под заголовком "обратные вызовы".
Стратегия ведет себя сродни классу Command, все наследуется от одного базового класса. Но если вы присмотритесь к Command, вы увидите, что они имеют одинаковую структуру: иерархия функционных объектов. Различие в способе использования этой иерархии. Как видно из refactor:DirList.java, вы используете Command для решения определенной задачи - в данном случае, для выбора файлов из списка. То, что "остается прежним" - это тело метода, который вызывает, а часть, которая меняется, изолирована в функционном объекте. Я рискну сказать, что Command предоставляет гибкость, пока вы пишите программу, в то время, как Strategy предоставляет гибкость во время выполнения. Тем не менее, это выглядит хрупким различием.
Упражнение
- Используйте команду из 1-го упражнения 3 главы.
← | Facade | Цепочка откликов (Chain of responsibility) | → |