Tuesday, June 14, 2022

Design Pattern: Command Pattern

Chapters

Command Pattern

Command pattern is a design pattern that wraps an object (receiver) to another object (command) with necessary information that can be processed by a handler (invoker). Command pattern consists of four entities: Client, Command, Receiver and Invoker.

Client is the one that uses our code. Could be a programmer or class. Command are classes that instantiate command objects. Command objects are objects that contain a receiver object and necessary information, sucn as function (instruction) to be called and variables, that is needed by an ivoker in order to perform requests that clients want.

Receiver are classes that instantiate receiver objects. Receiver objects are objects that are receiving commands. Invoker are classes that instantiate invoker objects. These objects contain commands that are executed by them.

This pattern promotes loose coupling between commands and handlers or executors. It means that commands and handlers don't need to be tighly coupled in order to function properly. Thus, increasing the flexibility of our code. Moreover, command pattern is often used in conjunction with chain-of-responsibility pattern.

This diagram shows how to implement a command pattern Diagram
Courtesy of Wikipedia

This example demonstrates command pattern.
//Client
public class ClientCode{
  
  public static void main(String[] args){
    
    //Receiver instance
    Controller computerController = 
    new ComputerController();
    Controller consoleController = 
    new ConsoleController();
   
    //command instance
    Command moveUp = 
    new MoveCommand(computerController,
                    Controller.DirectMove.UP);
    Command moveTopLeft = 
    new MoveDiagonalCommand(
    computerController,
    Controller.DiagonalMove.TOP_LEFT);
    
    //Invoker instance
    MoveInput controllerInput = 
    new MoveInput(moveUp, moveTopLeft);  
    controllerInput.move();
    controllerInput.moveDiagonally();
    System.out.println();  
    
    //Command instance
    Command moveDown = 
    new MoveCommand(consoleController,
                    Controller.DirectMove.DOWN);
    Command moveBotRight = 
    new MoveDiagonalCommand(
    consoleController,
    Controller.DiagonalMove.BOTTOM_RIGHT);
    
    MoveInput consoleInput = 
    new MoveInput(moveDown, moveBotRight);
    consoleInput.move();
    consoleInput.moveDiagonally();
  
  }
}

//Receiver interface
interface Controller{
  public enum DirectMove{
    UP, RIGHT, DOWN, LEFT
  }
  
  public enum DiagonalMove{
    TOP_LEFT, TOP_RIGHT, 
    BOTTOM_LEFT, BOTTOM_RIGHT
  }
  
  void move(DirectMove direction);
  void moveDiagonally(DiagonalMove direction);
}
  
//Receiver
class ConsoleController implements Controller{
  
  @Override
  public void move(DirectMove direction){
    System.out.println
    ("Console controller moves " + direction);
  }
  
  @Override
  public void moveDiagonally(DiagonalMove direction){
    System.out.println
    ("Console controller diagonally moves " + direction);
  }
}
  
//Receiver
class ComputerController implements Controller{
  
  @Override
  public void move(DirectMove direction){
    System.out.println
    ("Computer controller moves " + direction);
  }
  
  @Override
  public void moveDiagonally(DiagonalMove direction){
    System.out.println
    ("Console controller diagonally moves " + direction);
  }
}

//command interface
interface Command{
  
  void execute();
}
  
//command
class MoveCommand implements Command{
  
  private Controller controller;
  private Controller.DirectMove movement;
  
  public MoveCommand(Controller controller,
                     Controller.DirectMove movement){
    this.controller = controller;
    this.movement = movement;
  }
  
  @Override
  public void execute(){
    controller.move(movement);
  }
}
  
//command
class MoveDiagonalCommand implements Command{
  
  private Controller controller;
  private Controller.DiagonalMove movement;
  
  public MoveDiagonalCommand(Controller controller,
                             Controller.DiagonalMove movement){
    this.controller = controller;
    this.movement = movement;
  }
  
  @Override
  public void execute(){
    controller.moveDiagonally(movement);
  }
}
  
//invoker
class MoveInput{
  private Command directMovement;
  private Command diagonalMovement;
  
  public MoveInput(Command directMovement,
                   Command diagonalMovement){
    this.directMovement = directMovement;
    this.diagonalMovement = diagonalMovement;
  }
  
  public void move(){
    directMovement.execute();
  }
  
  public void moveDiagonally(){
    diagonalMovement.execute();
  }
}
  
Result
Computer controller move UP
Computer controller diagonally moves TOP_LEFT
  
Console controller moves DOWN
Console controller diagonally moves BOTTOM_RIGHT

No comments:

Post a Comment