JavaRush /Java блог /Random UA /Паттерн Command своїми словами
Roman_kh
33 рівень
Харьков

Паттерн Command своїми словами

Стаття з групи Random UA

Привіт усім, Форумчани!

Розібрався-таки ґрунтовно (як мені здається) з патером Commandі хочу спробувати розповісти про нього "своїми словами". Паттерн Command своїми словами - 1Виходячи з Вікіпедії, можемо дізнатися, що мета його - це створення структури, в якій клас-відправник та клас-одержувач не залежать один від одного безпосередньо. Організація зворотного виклику до класу, який включає клас-відправник. У принципі написано чітко і правильно, але це теоретично. А як це зробити? Саме цим починаються проблеми, т.к. опис не так ясно і очевидно. Тому я як розібрався, вирішив розповісти вам як я це зрозумів, може комусь і знадобиться: Виходячи з опису мети цього патерна, комбінуватиму опис відразу з кодом, щоб було наочніше, т.к. у тій самій вікіпедії узагальнабо для багатьох мов і тому опис відокремлено від прикладу. У цьому патерні є чотири терміни, поки приймемо їх як даність: команди( command), приймач команд( receiver), що викликає команди( invoker) та клієнт( client). Приклад братиму з тієї ж Вікіпедії, він цілком стерпний. Завдання є клас Light, який вміє дві речі: увімкнути світло і вимкнути. Він у термінах патерну буде "приймач команд (receiver)"
/*Receiver class*/

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)"
/*the Command interface*/

public interface Command{
    void execute();
}
Необхідно інкапсулювати виконання умінь класу Light. Для цього ми створимо класи TurnOnLightCommandта TurnOffLightCommand, які реалізують інтерфейс Commandі які прийматимуть у конструкторі об'єкт класу Light. І кожен із них виконуватиме лише одну дію. Один викликатиме метод turnOn(), а інший turnOff().
/*the Command for turning on the light*/

public class TurnOnLightCommand implements Command{
   private Light theLight;

   public TurnOnLightCommand(Light light){
        this.theLight=light;
       }

   public void execute(){
      theLight.turnOn();
   }
}

/*the Command for turning off the light*/

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().
/*the Invoker class*/

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, в якому і відбуватиметься вся дія:
/*The test class*/
public class TestCommand{
   public static void main(String[] args){
       // создаем об'єкт, который будет использоваться
       Light l=new Light();
       // создаем об'єкты для всех умений об'єкта Light:
       Command switchUp=new TurnOnLightCommand(l);
       Command switchDown=new TurnOffLightCommand(l);

       // Создаемтся invoker, с которым мы будем непосредственно контактировать:
       Switch s=new Switch(switchUp,switchDown);

       // вот проверка этого, используем методы:
       s.flipUp();
       s.flipDown();
   }
}
На висновку буде наступне:
"The light is on"
"The light is off"

Де це застосовується?

По меті ясно, що й навіщо це потрібно, саме: у ситуації, коли потрібно відокремити конкретне виконання, дуже зручно. Щоб використання якихось функцій не залежало від конкретної реалізації і можна було змінювати без шкоди системи. якось так ...) Пишіть свої коментарі, давайте обговорювати, може щось можна зробити простіше і розповісти краще, будемо все правити, якщо необхідно) Щоб для тих, хто читатиме перший раз, було якомога зрозуміліше. Ну і кому сподобається стаття - ставить "+" на ній :) Для мене це важливо) Згодом хочу написати ще про Builder, Singletonта інші. також мої інші статті:
Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ