Comando (padrão de desenho)

From Wiki**3

The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.
Programação com Objectos
Introduction
Creation and Destruction
Inheritance & Composition
Abstraction & Polymorphism
Code Organization
Java Topics
Inner Classes
Enumerations
Data Structures
Exceptions
Input/Output
RTTI
Other Topics
JUnit Tests
UML Topics
Design Patterns
"Simple" Factory
Composite & Visitor
Command
Strategy & State
Template Method
Observer
Abstract Factory
Decorator & Adapter
Façade (aka Facade)

O padrão comando permite encapsular um comando ou pedido num objecto. Assim, os clientes podem ser parametrizados com comandos variados e os comandos podem ser manipulados para atingir vários fins: é possível atrasar a sua execução, colocá-los em filas de espera e registar a sua execução. É ainda possível suportar a execução da inversão das acções das operações relativas a um comando (undo).

Estrutura

Diagrama de classes

O padrão comando tem a seguinte estrutura de classes:

Diagrama de sequência

As colaborações entre os intervenientes são as que figuram no seguinte diagrama de sequência:

Exemplo

Considerando o código na biblioteca po-uuilib (ver link abaixo), podem ser definidos comando como os seguintes.

Cada subclasse de Command deve providenciar o tipo do "receiver", assim como a instância (a superclasse -- Command -- apenas suporta um receptor de comandos, mas é possível definir outros que sejam necessários nas subclasses).

Exemplo de subclasse de Command (neste caso, apresenta-se, apenas a título de exemplo, uma operação fictícia sobre o tipo Cat, suposto definido):

public class DoChaseLaserDot extends Command<Cat> {
        public DoChaseLaserDot(Cat receiver) {
                super(Label.CHASE_LASER_DOT, receiver);
        }

        public final void execute() {
          // DO SOMETHING
        }
}

Exemplo de definição de subclasse de Command, fazendo uso da funcionalidade de validação dinâmica dos comandos (os comandos por omissão são sempre válidos -- ver código). Neste exemplo, assume-se que o método isReady está definido na classe Cat. O menu não apresentará o comando e não permitirá a sua invocação. No entanto, o método execute não é afectado (esta opção destina-se a simplificar as decisões, mas pode ter consequências imprevisíveis se um comando inválido for executado sem o teste ser efectuado).

public class DoChaseLaserDot extends Command<Cat> {
        public DoChaseLaserDot(Cat receiver) {
                super(Label.CHASE_LASER_DOT, receiver, receiver -> receiver.isReady());
        }

        public final void execute() {
          // DO SOMETHING
        }
}

A definição do método isValid é inteiramente dependente do domínio. Por omissão, o predicado é sempre verdadeiro.

Exercícios