→ Пошук по сайту       Увійти / Зареєструватися
Знання Патерни Патерни поведінки — Behavioral patterns

14. Команда — Command

14.	Команда — Command

Ваш бос дуже вимогливий — він ніколи не переймається тим, як буде робитися робота і не особливо переймається тим, хто її буде робити – йому головне щоб вона була зроблена, як тільки замовник дасть добро. Проте вашому босу ніхто не заважає назначати людей, які будуть працювати над виконанням завдання. Він вирішив, що ви, оскільки ви на високих позиціях у компанії, ідеально підходете для того, щоб зібрати бригаду, отримати список вимог від замовника і бути готовими запустити роботу, як тільки замовник підпише контракт.

Команда дозволяє інкапсулювати всю інформацію, необхідну для виконання певних операцій, які можуть бути виконані пізніше, використавши об’єкт команди.

В нашому прикладі ви є Командою (сommand) — тому що ви інкапсулюєте справжню робочу групу і параметри, необхідні для старту роботи (проект і вимоги). Бригада, що є отримувачем (receiver) роботи, а також вимоги і інші параметри, були вам передані вашим босом (клієнтським кодом).

Замовник має зв’язок із вами і може попросити вас виконати всю необхідну роботу як тільки запуститься процес після підписання контракту. Замовник — це ваш запускач (invoker), він знає як попросити вас виконати роботу тоді, коли це йому зручно.

А зараз трошки глянемо на код. Ось клієнтський код, що презентує вашого боса:

Уривок коду 14.1. Використання патерну — клієнтський код

 // Замовник
var customer = new Customer();
// Із певних міркуваня, бос завжди знає, що грошей стає тільки
// на бригаду Z
var team = new Team("Z");
// Також бос отримав список вимог, що треба буде передати бригаді
var requirements = new List<Requirement>() { new Requirement("Cool web site"),
 new Requirement("Ability to book beer on site") };
// Ви повинні бути готові бути викликаними замовником
ICommand commandX = new YouAsProjectManagerCommand(team, requirements);
// Передача вас у «найми» замовнику 
customer.AddCommand(commandX);


// В компанії також є програміст-герой, що кодує на швидкості світла
var heroDeveloper = new HeroDeveloper();
// Бос вирішив віддати йому проект A
ICommand commandA = new HeroDeveloperCommand(heroDeveloper, "A");
customer.AddCommand(commandA);

// Як тільки замовник підписує контракт із вашим босом,
// ваша бригада і програміст-герой готові виконати все, що треба
// згідно вихідного коду контракту
customer.SignContractWithBoss();

Нижче наведені два приклади конкретної реалізації команд.

Уривок коду 14.2. Команда

 public interface ICommand
{
    // Кожна Команда має метод для її запуску
    void Execute();
}
// Приклад однієї із Команд до виконання
class YouAsProjectManagerCommand : ICommand
{
    public YouAsProjectManagerCommand(Team team, List<Requirement> requirements)
    {
        Team = team;
        Requirements = requirements;
    }
    public void Execute()
    {
        // Реалізація делегує роботу до потрібного отримувача
        Team.CompleteProject(Requirements);
    }
    protected Team Team { get; set; }
    protected List<Requirement> Requirements { get; set; }
}
// І ще один приклад
class HeroDeveloperCommand : ICommand
{
    public HeroDeveloperCommand(HeroDeveloper heroDeveloper, string projectName)
    {
        HeroDeveloper = heroDeveloper;
        ProjectName = projectName;
    }
    public void Execute()
    {
        // Реалізація делегує роботу до потрібного отримувача
        HeroDeveloper.DoAllHardWork(ProjectName);
    }
    protected HeroDeveloper HeroDeveloper { get; set; }
    public string ProjectName { get; set; }
}

Team та HeroDeveloper є отримувачами роботи, яка має бути зроблена. Об’єкти цих класів передаються в команди разом із іншими параметами. Як на диво, програмісту-герою достатньо назви проекту для його виконання, а вам (YouAsProjectManagerCommand) все ж таки потрібні вимоги.
Замовник насправді не дуже переймається тим, хто буде робити його роботу, але він чітко знає що хоче її зробити, тому він викликає метод Execute для кожної доступної йому команди, зразу ж після підписання контракту.

Уривок коду 14.3. Замовник — володіє командами і запускає їх

 class Customer
{
    protected List<ICommand> Commands { get; set; }
    public Customer()
    {
        Commands = new List<ICommand>();
    }
    public void AddCommand(ICommand command)
    {
        Commands.Add(command);
    }
    public void SignContractWithBoss()
    {
        foreach (var command in Commands)
        {
            command.Execute();
        }
    }
}

Вивід:

 User Story (Cool web site) has been completed
User Story (Ability to book beer on site) has been completed
Hero developer completed project (A) without requirements in manner of couple hours!

Взаємодія між цими всіма класами є точно така ж, як і в класичному поясненні патерну, тому діаграми не наводжу — її легко знайти в інтернеті. Для асоціацій використовуйте англомовні назви в дужках.

Але із тієї самої причини, що це класичний приклад, взаємодія є досить громіздка. Тому пам’ятайте ключові моменти — команда інкапсулює інформацію і надає назовні один метод для виконання дій. Сама команда, як об’єкт, може бути переслана до будь-яких закутків вашого коду, де її можуть успішно використати.

По матеріалам книги Андрія Будая "Дизайн патерни – просто, як двері". Матеріал розміщується за домовленістю з автором.
Робота представлена за умовами ліцензії Creative Commons Attribution-NonCommercial 3.0 Unported License.

загрузка...
Сторінки, близькі за змістом