Привіт усім, Форумчани!
Розібрався-таки ґрунтовно (як мені здається) з патером
Command
і хочу спробувати розповісти про нього "своїми словами".
Виходячи з Вікіпедії, можемо дізнатися, що мета його - це
створення структури, в якій клас-відправник та клас-одержувач не залежать один від одного безпосередньо. Організація зворотного виклику до класу, який включає клас-відправник. У принципі написано чітко і правильно, але це теоретично. А як це зробити? Саме цим починаються проблеми, т.к. опис не так ясно і очевидно. Тому я як розібрався, вирішив розповісти вам як я це зрозумів, може комусь і знадобиться: Виходячи з опису мети цього патерна, комбінуватиму опис відразу з кодом, щоб було наочніше, т.к. у тій самій вікіпедії узагальнабо для багатьох мов і тому опис відокремлено від прикладу. У цьому патерні є чотири терміни, поки приймемо їх як даність: команди(
command
), приймач команд(
receiver
), що викликає команди(
invoker
) та клієнт(
client
). Приклад братиму з тієї ж Вікіпедії, він цілком стерпний.
Завдання є клас
Light
, який вміє дві речі: увімкнути світло і вимкнути. Він у термінах патерну буде "приймач команд (
receiver
)"
public class Light{
public Light(){ }
public void turnOn(){
System.out.println("The light is on");
}
public void turnOff(){
System.out.println("The light is off");
}
}
Створимо інтерфейс з одним методом
execute()
, який виконуватиме і який називається в термінах патерну "команда (
command
)"
public interface Command{
void execute();
}
Необхідно інкапсулювати виконання умінь класу
Light
. Для цього ми створимо класи
TurnOnLightCommand
та
TurnOffLightCommand
, які реалізують інтерфейс
Command
і які прийматимуть у конструкторі об'єкт класу
Light
. І кожен із них виконуватиме лише одну дію. Один викликатиме метод
turnOn()
, а інший
turnOff()
.
public class TurnOnLightCommand implements Command{
private Light theLight;
public TurnOnLightCommand(Light light){
this.theLight=light;
}
public void execute(){
theLight.turnOn();
}
}
public class TurnOffLightCommand implements Command{
private Light theLight;
public TurnOffLightCommand(Light light){
this.theLight=light;
}
public void execute(){
theLight.turnOff();
}
}
Тепер настав час створити об'єкт, який приймав ці інкапсульовані методи об'єкта
Light
. Він у термінах патерну називається викликає команди (invoker). Назвемо його
Switch
і нехай він прийматиме в конструкторі змінні
Command
, які будуть використовуватися у створених методах
flipUp()
та
flipDown()
.
public class Switch {
private Command flipUpCommand;
private Command flipDownCommand;
public Switch(Command flipUpCommand,Command flipDownCommand){
this.flipUpCommand=flipUpCommand;
this.flipDownCommand=flipDownCommand;
}
public void flipUp(){
flipUpCommand.execute();
}
public void flipDown(){
flipDownCommand.execute();
}
}
Ну і звичайно створимо клас, який буде використовувати їх, щоб зрозуміти, що відбувається взагалі. Він буде називати метод main, в якому і відбуватиметься вся дія:
public class TestCommand{
public static void main(String[] args){
Light l=new Light();
Command switchUp=new TurnOnLightCommand(l);
Command switchDown=new TurnOffLightCommand(l);
Switch s=new Switch(switchUp,switchDown);
s.flipUp();
s.flipDown();
}
}
На висновку буде наступне:
"The light is on"
"The light is off"
Де це застосовується?
По меті ясно, що й навіщо це потрібно, саме: у ситуації, коли потрібно відокремити конкретне виконання, дуже зручно. Щоб використання якихось функцій не залежало від конкретної реалізації і можна було змінювати без шкоди системи. якось так ...) Пишіть свої коментарі, давайте обговорювати, може щось можна зробити простіше і розповісти краще, будемо все правити, якщо необхідно) Щоб для тих, хто читатиме перший раз, було якомога зрозуміліше. Ну і кому сподобається стаття - ставить "+" на ній :) Для мене це важливо) Згодом хочу написати ще про
Builder
,
Singleton
та інші.
також мої інші статті:
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ