Overview

Purpose

Use When

Example

Given Hardware

hw

Our Vendor Classes

vendor

Without Using Command Pattern

if(command == Slot1On)
    light.on();
else if(command == Slot1Off)
    light.off();

Implementing Command interface

public interface Command {
    public void execute();
}

Implementing a command

public class LightOnCommand implements Command {
    Light light; // Stores info. about its receiver

    public LightOnCommand(Light light) {
        this.light = light;
    }

    public void execute() {
        light.on();
    }
}

Using the command object (Building Invoker)

public class SimpleRemoteControl {
    Command slot;

    public SimpleRemoteControl() {}

    public void setCommand(Command command) {
        slot = command;
    }

    public void buttonWasPressed(){
        slot.execute();
    }
}

Client Program

public class RemoteControlTest {
    public static void main(String[] args) {
        SimpleRemoteControl remoteControl = new SimpleRemoteControl();

        Light light = new Light();
        LightOnCommand lightOn = new LightOnCommand(light);

        remote.setCommand(lightOn);
        remote.buttonWasPressed();
    }
}
public class SimpleRemoteControl {
    Command slot;
    public void buttonWasPressed(){
        slot.execute();
    }
}
public class LightOnCommand implements Command {
    Light light;
    public void execute() {
        light.on();
    }
}

Command Pattern

public class LightOffCommand implements Command {
    Light light; // Stores info. about its receiver

    public LightOffCommand(Light light) {
        this.light = light;
    }

    public void execute() {
        light.off();
    }
}

Our Approach

approach
uml

Collaborations

coll

Extending the Remote Control

public class RemoteControl {
    Command[] onCommands;
    Command[] offCommands;

    RemoteControl() {
        onCommands = new Command[7];
        offCommands = new Command[7];

        Command noCommand = new NoCommand(); // null objecet

        for(int i = 0; i < 7; ++i) {
            onCommands[i] = noCommand;
            offCommands[i] = noCommand;
        }
    }
}

public class NoCommand implements Command {
    public void execute() {}
}

Command Pattern

public void setCommand(int slot, Command onCommand, Command offCommand) {
    onCommands[slot] = onCommand;
    onCommands[slot] = offCommand;
}

public void onButtonWasPushed (int slot) {
    onCommands[slot].execute();
}

public void offButtonWasPushed (int slot) {
    offCommand[slot].execute();
}

Client Program

public class RemoteLoader {
    public static void main(String[] args) {
        // create invoker
        RemoteControl remotecontrol = new RemoteControl();

        // create receivers
        Light livingRoomLight = new Light("Living Room");
        Light kitchenLight = new Light("Kitchen");

        // create commands
        Command livingRoomLightOn = new LightOnCommand(livingRoomLight);
        Command livingRoomLightOff = new LightOffComman(livingRoomLight);
        Command kitchenlightOn = new LightOnCommand(kitchenLight);
        Command kitchenlightOff = new LightOffCommand(kitchenLight);

        // linking the invoker with the commands
        remotecontrol.setCommand(0,livingRoomLightOn,livingRoomLightOff);
        remotecontrol.setCommand(1,kitchenlightOn,kitchenlightOff);
        remotecoltrol.onButtonWasPushed(0);
        remotecoltrol.offButtonWasPushed(0);
        remotecoltrol.onButtonWasPushed(1);
        remotecoltrol.offButtonWasPushed(1);
    }
}

After Setting the Commands

after

Supporting Undo

public class LightOnCommand implements Command {
    Light light;
    public LightOnCommand(Light light){
        this.light = light;
    }

    public void execute() {
        light.on();
    }

    public void undo() {
        light.off();
    }
}

public void onButtonWaspressd(int slot) {
    onCommands[slot].execute();
    undoCommand = onCommands[slot];
}

public void offButtonWaspressd(int slot){
    offCommands[slot].execute();
    undocommand = offCommands[slot];
}

public void undoButtonWaspressd(){
    undocommand.undo();
}

Supporting Macro Commands

public class MacroCommand implements Command {
    Command[] command;

    public MacroCommand(Command[] command){
        this.command = command;
    }

    public void execute(){
        for(int i = 0; i < command.length; i++)
            command[i].execute();
    }
}

Command + Iterator

public class MacroCommand implements Command {
    ArrayList <Command>commands;

    public MacroCommand(Command[] commands) { 
        this.commands = new ArrayList();
        for (int i=0; i< commands.length; i++)
            this.commands.add(commands[i]);
    }

    public void execute() {
        for (Command item: this.commands)
            item.execute(); 
    }

    // NOTE: commands have to be done backwards to ensure proper undo
    public void undo() {
        ListIterator<Command> i=commands.listIterator(commands.size());
        while (i.hasPrevious())
            i.previous().undo(); 
    }
}

Active Object Pattern

interface Command {
    public void execute();
}

class ActiveObjectEngine {
    LinkedList itsCommands = new LinkedList();

    public void addCommand(Command c) {
        itsCommands.add(c);
    }

    public void run() {
        while (!itsCommands.isEmpty()) {
            Command c = (Command) itsCommands.getFirst();
            itsCommands.removeFirst();
            c.execute();
        }
    }
}

class SleepCommand implements Command {
    private Command wakeupCommand = null;
    private ActiveObjectEngine engine = null;
    private long sleepTime = 0; private long startTime = 0;
    private boolean started = false;

    public SleepCommand(long milliseconds, ActiveObjectEngine e, Command wakeupCommand) {
        sleepTime = milliseconds;
        engine = e;
        this.wakeupCommand = wakeupCommand;
    }

    public void execute() {
        long currentTime = System.currentTimeMillis();

        if (!started) {
            started = true;
            startTime = currentTime;
            engine.addCommand(this);
        } else if ((currentTime - startTime) < sleepTime ) {
            engine.addCommand(this);
        } else 
            engine.addCommand(wakeupCommand);
    }
}

public class DelayedTyper implements Command {
    private long mDelay = 0;
    private char mChar;
    private static boolean stop = false;
    private static ActiveObjectEngine engine = new ActiveObjectEngine(); 
    
    public DelayedTyper(long delay, char c) {
        mDelay = delay;
        mChar = c;
    }

    @Override
    public void execute() {
        System.out.print(mChar);
        
        if (!stop) delayAndRepeat();
    }

    private void delayAndRepeat() {
        engine.addCommand(new SleepCommand(mDelay, engine, this));
    } 

    public static void main(String args[]) throws Exception {
        engine.addCommand(new DelayedTyper(100, '1'));
        engine.addCommand(new DelayedTyper(300, '3'));
        engine.addCommand(new DelayedTyper(500, '5'));
        engine.addCommand(new DelayedTyper(700, '7')); 

        Command stopCommand = new Command() { 
            @Override public void execute() {
                stop = true;
            }
        }; 

        engine.addCommand(new SleepCommand(10000, engine, stopCommand)); 
        engine.run();
    }
} 

Class Diagram for DelayedTyper

diagram

Review