designpatterns-09.pdf

Upload: kiranshingote

Post on 03-Apr-2018

221 views

Category:

Documents


0 download

TRANSCRIPT

  • 7/29/2019 designPatterns-09.pdf

    1/29

    The Command Pattern

    CSCI 3132 Summer 20111

  • 7/29/2019 designPatterns-09.pdf

    2/29

    Example:RemoteControl

    Givenremotecontrolwithsevenprogrammableslots.

    Adifferentdevicecanbeputintoeachslot. ThereisanOnandOffswitchforeachdeviceslot. GlobalUndobuBonundoesthelastbuBonpressed. AlsogivenaCDwithdifferentvendorclassesthat

    havealreadybeenwriBen(forthedifferentdevices,

    TV,Light,Sprinkler,etc)

    2

  • 7/29/2019 designPatterns-09.pdf

    3/29

    FirstThoughts

    Weknowthattherearesevenprogrammableslotsfordifferentdevicessoeachdevicemaypossibly

    adheretosomecommoninterface.

    Weknowthatweneedtoturneachdeviceonoroff..sothatneedstobecommonlydoneforany

    device.

    Undoneedstoworkforanydeviceaswell.

    3

  • 7/29/2019 designPatterns-09.pdf

    4/29

    WhatVaries?Whatstaysthesame?

    WhatVariesTheactualdeviceassignedtoaslotTheinstruconforOnonaspecificdeviceTheinstruconforOffonaspecificdevice

    WhatStaystheSameDevicewithsevenslotsCapabilitytoassignaslottoadeviceCapabilitytorequestthatadeviceturnOnorOffCapabilitytoundothelastaconrequestedagainst

    thedevice

    4

  • 7/29/2019 designPatterns-09.pdf

    5/29

    TheVendorClasses

    VendorclasseshavebeenprovidedtousviaaCD.CeilingLightTV

    HoBub

    WeknowthateachdeviceneedsanOnorOffstate.

    SincethecapabilitytoturnadeviceOnorOffissomethingthatstaysthesame.

    However,eachvendorclasshastheirownuniquewayofdoingOnorOff.

    5

  • 7/29/2019 designPatterns-09.pdf

    6/29

    Onepossiblesoluon

    if (slot1 == Light)

    light.on();

    Else if (slot1 == Hottub) {

    hottub.prepareJets();

    hottub.jetsOn();

    } Else if (slot1 == TV)

    tv.on();

    //

    Problems:

    The Remote needs to beaware of all the details aboutturning a device on (or off).

    If device On/Off mechanism

    changes, the Remote codewill need to be changed.

    If a new device is added, this

    code would need to bechanged.

    Is this Open forExtension??

    Alsowhat aboutundo????

    6

  • 7/29/2019 designPatterns-09.pdf

    7/29

    SeparaonofConcerns

    TheVendorClass One(ormore)methodsthatdefineOn One(ormore)methodsthatdefineOff

    TheCommand Sendsamessagetoadevice(OnorOff) Handletheundoofamessage Possiblefutureenhancements

    LoggingrequestQueuerequest

    TheRemotehandlesoneormoreCommands.TheRemotedoesntknowanythingabouttheactual

    vendorclassspecifics.7

  • 7/29/2019 designPatterns-09.pdf

    8/29

    TheCommandPaBern

    Allowsyoutodecoupletherequestoroftheaconfromtheobjectthatperformstheacon.

    ACommandobjectencapsulatesarequesttodosomething.

    Note:ACommandobjecthandlesasinglerequest. TheCommandinterface(inthisexample)justdoes

    onethingexecutesacommand.

    8

  • 7/29/2019 designPatterns-09.pdf

    9/29

    LightOnCommandAcommand

    public class LightOnCommand implements Command {

    Light light;

    public LightOnCommand(Light light) {

    this.light = light;

    }

    public void execute() {

    light.on();}

    }

    The command is

    composed of a vendorclass.

    Constructor takes the

    vendor class asparameter.

    Here the command delegates

    execution to the vendor class.Could be more steps.

    9

  • 7/29/2019 designPatterns-09.pdf

    10/29

    SimpleRemoteControlAninvoker

    public class SimpleRemoteControl {

    Command slot;

    public SimpleRemoteControl() {}

    public void setCommand(Command command) {

    slot = command;

    }

    public void buttonWasPressed() {

    slot.execute();

    }

    }

    This version of the

    remote just has oneslot.

    setCommand assigns

    a Command to a slot.

    Tells the command to

    execute. Note that anycommand would work

    here. The remotedoesnt know anything

    about the specific

    vendor class.10

  • 7/29/2019 designPatterns-09.pdf

    11/29

    Encapsulaon

    action()

    execute()

    { receiver.action

    ()

    }

    execute()

    execute()

    execute()

    An encapsulated Request

    Invoker

    Command encapsulates a Receiver object, use delegation to thecorresponding device,Different commands can fit into a Remote Slot in the remote control.

    11

  • 7/29/2019 designPatterns-09.pdf

    12/29

    RemoteControlTestAclient

    SimpleRemoteControl remote = new SimpleRemoteControl();

    Light light = new Light();

    GarageDoor garageDoor = new GarageDoor();

    LightOnCommand lightOn =

    new LightOnCommand(light);

    GarageDoorOpenCommand garageOpen =

    new GarageDoorOpenCommand(garageDoor);

    remote.setCommand(lightOn);remote.buttonWasPressed();

    remote.setCommand(garageOpen);

    remote.buttonWasPressed();

    Create two vendor

    classes.

    Create two commandsbased on these vendorclasses.

    Set the command and press

    button

    12

  • 7/29/2019 designPatterns-09.pdf

    13/29

    TheCommandPaBern

    GoFIntent:Encapsulatesarequestasanobject,therebyle\ngyouparameterizeotherobjectswithdifferent

    requests,queueorlogrequests,andsupportundoable

    operaons.

    Par(cipants: Client(RemoteControlTest)createscommandandassociatescommand

    withreceiver.

    Receiver(TV,HotTub,ec)knowshowtoperformthework. ConcreteCommand(LightOnCommand)-implementaonofCommand

    interface

    CommandInterfacedefinesinterfaceforallcommands. Invoker(RemoteControl)holdsreferencetoacommandandcalls

    execute()method

    13

  • 7/29/2019 designPatterns-09.pdf

    14/29

    CommandPaBernClassDiagram

    Client Invoker

    setCommand()

    Command

    execute()undo()

    Receiver

    action()

    ConcreteCommand

    execute()undo()

    ClientcreatesaConcreteCommandandbindsitwithaReceiver. ClienthandstheConcreteCommandovertotheInvokerwhichstores

    it.14

  • 7/29/2019 designPatterns-09.pdf

    15/29

    TheSequenceDiagram

    15

  • 7/29/2019 designPatterns-09.pdf

    16/29

    ClassDiagramforHomeautomaon

    RemoteLoader

    RemoteControl

    onCommandsoffCommandssetCommand()onButtonPushed()offButtonPushed()

    Command

    execute()undo()

    Light

    on()

    off()

    LightOnCommand

    execute()undo()LightOffCommand

    execute()undo()

    Creates command objects,binds with devices

    Invokes execute() method ofthe button command object

    16

  • 7/29/2019 designPatterns-09.pdf

    17/29

    MacroCommandsPartymode

    public class MacroCommand implements Command {

    Command[] commands;

    public MacroCommand(Command[] commands) {

    this.commands = commands;

    }

    public void execute() {

    for (int i = 0; i < commands.length; i++) {

    commands[i].execute();

    }

    }

    public void undo() {for (int i = 0; i < commands.length; i++) {

    commands[i].undo();

    }

    }

    }

    17

  • 7/29/2019 designPatterns-09.pdf

    18/29

    Easyforsomeobjects

    public class LightOnCommand implements Command {

    Light light;

    public LightOnCOmmand(Light light) {

    this.light = light;

    }

    public void execute() {

    light.on();

    }

    public void undo() {

    light.off();}

    }

    AddingUndo

    18

  • 7/29/2019 designPatterns-09.pdf

    19/29

    Implemenngtheremotecontrolwithundo.public class RemoteControl {

    Command[] on Commands;

    Command[] offCommands;

    Command[] undoCommands;

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

    offCommands = new Command[7];

    Command noCommand = new NoCommand();

    for (int i = 0; i < 7; i++) {

    onCommands[i] = noCommand;

    offCommands[i] = noCommand;}

    undoCommand = noCommand;

    }

    public void setCommand(int slot, Command onCommand, CommandoffCommand) {

    onCommand[slot] = onCommand;

    offCommand[slot] = offCommand;

    }

    AddingUndo

    19

  • 7/29/2019 designPatterns-09.pdf

    20/29

    public void onButtonWasPushed(int slot) {

    onCommands(slot].execute();

    undoCommand = onCommands[slot];

    }

    public void offButtonWasPushed(int slot) {offCommands(slot].execute();

    undoCommand = offCommands[slot];

    }

    public void undoButtonwWasPushed() {

    undoCommand.undo();

    }

    //

    }

    AddingUndo

    20

  • 7/29/2019 designPatterns-09.pdf

    21/29

    public class CeilingFan {

    public static final int HIGH = 3;public static final int MEDIUM = 2;

    public static final int LOW= 1;

    public static final int OFF= 0;

    public CeilingFan(String location) {

    this.location = location;

    speed = OFF;}

    public void high() {

    speed = HIGH;

    //code to set fan to high

    }

    public void medium() {

    speed = MEDIUM;//code to set fan to medium

    }

    //

    public void off() {

    speed = OFF;

    //code to turn fan off

    }

    AddingUndoForCeilingFan

    21

  • 7/29/2019 designPatterns-09.pdf

    22/29

    public class CeilingFanHighCommand implements Command {CeilingFan ceilingFan;

    int prevSpeed;

    public CeilingFanHighCommand(CeilingFan ceilingFan) {

    this.ceilingFan = ceilingFan;

    }

    public void execute() {prevSpeed = ceilingFan.getSpeed();

    ceilingFan.high();

    }

    public void undo() {

    if (prevSpeed == CeilingFan.HIGH) {

    celingFan.high();

    } else if (prevSpeed = CeilingFan.MEDIUM) {

    ceilingFan.medium();

    } else if (prevSpeed = CeilingFan.LOW) {

    ceilingFan.low();

    } else if (prevSpeed = CeilingFan.OFF) {

    ceilingFan.off();}}

    AddingUndoForCeilingFan

    22

  • 7/29/2019 designPatterns-09.pdf

    23/29

    HistoryofUndoOperaons

    IftheUndobuBonispressedmulplemes,wewanttoundoeachcommandthathadbeenpreviouslyapplied.

    Whichobjectshouldweenhancetostoreahistoryofeachcommandapplied?Why?

    Client(RemoteControlTest) Receiver(TV,DVD,etc) ConcreteCommand(LightOnCommand,LightOffCommand,

    etc)

    Invoker(RemoteControl) Weneedtobeabletoaddcommandstoalistandthenlater

    getthemostrecentone.Whatkindofobjectcanweuse?

    23

  • 7/29/2019 designPatterns-09.pdf

    24/29

    HistoryofUndoOperaonspublic class RemoteControl {

    Stack undoStack; //this gets initialized in

    //constructor.

    public void onButtonWasPushed(int slot) {

    onCommands[slot].execute();

    undoStack.push(onCommands[slot]);

    }

    public void offButtonWasPushed(int slot) {

    offCommands[slot].execute();

    undoStack.push(offCommands[slot]);

    }

    public void undoButtonWasPushed() {

    Command c = undoStack.pop();

    c.undo();

    } 24

  • 7/29/2019 designPatterns-09.pdf

    25/29

    SimpleLogging

    WewanttoenhancetheRemoteControlagaintologeverymeaCommandisexecuted(onoroff).

    Whichobjectshouldweenhance??

    25

  • 7/29/2019 designPatterns-09.pdf

    26/29

    SimpleLogging

    ChangestoRemoteControl public void onButtonWasPushed(int slot) {

    onCommands[slot].execute();

    //Log here

    }

    public void offButtonWasPushed(int slot) {

    offCommands[slot].execute();

    //Log here

    }

    Advantage: We can add logging in the Invoker. Nochange is needed in any of the Command or Receiverobjects! 26

  • 7/29/2019 designPatterns-09.pdf

    27/29

    ComplexLogging

    Letssaywehadaspreadsheetapplicaonandweknowit

    maycrashoen.

    Forfailurerecovery,wecouldperiodicallystoreabackupof

    thespreadsheetevery5minutes...orwecould

    periodicallypersistthelistofcommandsexecutedonthespreadsheetsincethelastsavepoint.

    Whenacrashoccurs,weloadthelastsaveddocumentand

    re-applythepersistedcommands.

    27

  • 7/29/2019 designPatterns-09.pdf

    28/29

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

    StoreToDisk(onCommands[slot]);

    }

    public void offButtonWasPushed(int slot) {

    offCommands[slot].execute();StoreToDisk(offCommands[slot]);

    }

    public void SaveButtonPressed() {

    //Delete stored commands from disk.

    }

    public void RestoreCommands() {

    //load last saved state

    Commands[] storedCommands = GetCommandsFromDisk();

    //for each Command, call execute()

    }

    ComplexLogging

    Once again,we can makethese changesin one place(the Invoker)

    28

  • 7/29/2019 designPatterns-09.pdf

    29/29

    Summarysofar..

    OOBasics Abstracon Encapsulaon Inheritance Polymorphism

    OOPrinciples Encapsulatewhatvaries Favorcomposionoverinheritance Programtointerfacesnottoimplementaons

    Striveforlooselycoupleddesignsbetweenobjectsthatinteract

    Classesshouldbeopenforextensionbutclosedformodificaon.

    Dependonabstracts.Donotdependonconcreteclasses.29