680 likes | 970 Views
Command Pattern. Mohammad Semnani 12 Aban 1392. Behavioral. Creational. Structural. Design Pattern. Design pattern is a general reusable solution to a commonly occurring problem within a given context in software design. Types of Patterns (GOF).
E N D
Command Pattern Mohammad Semnani 12 Aban 1392 Behavioral Creational Structural
Design Pattern • Design pattern is a general reusable solution to a commonly occurring problem within a given context in software design
Types of Patterns (GOF) • Behavioral Patterns: characterize the ways in which classes and objects communicate and distribute responsibilities • Creational Patterns: deal with object creation mechanisms, trying to create objects in a manner suitable to the situation • Structural Patterns: ease the design by identifying a simple way to realize relationships between entities ( deal with the composition of classes and objects)
Home Automation • Remote Control has seven slots (each can be assigned to a different household device) with corresponding ON/OFF buttons for each • Control current devices, and future devices • A global undo button
First solution • A set of if statements: • If slot1 == Light then light.on(); • Else if slot1 == GarageDoor then garageDoor.up();
problem • Calling a method tightly couples the invoking class to the receiving class • The invoker must specify: • Which object to call • Which method to call • What parameters to send with the call Design Pattern ته • Sometimes it is useful for a class to be able to invoke an operation on another class without having knowledge of what class it is calling, what method is being called, or what parameters are being sent
Command Pattern might help • It decouple the requesterof an action from the object that actually performs the action • Remote : Requester • Performer : one of devices • Is it possible? YESK آخر Design Pattern
How? • By introducing Command objects • A Command object encapsulates a request to do something (like turn on the light) on a specific object (say, the living room light object) • So, if we store a command object for each button, when the button is pressed, we ask the command object to do some work • The remote doesn’t have any idea what the work is! • It just has a command object that knows how to talk to the right object to get the job done
Lets see another example • Fast Food
Order • An Order Slip encapsulates a request to prepare a meal. • It has an interface with just one method, orderUp() that encapsulates the actions needed to prepare the meal • It also has the reference to the object that needs to prepare it (here : cook) • It is encapsulated in that the waitress doesn’t have to know 1. what’s in the order or 2. who prepares the meal
Waitress • The Waitress’s job is to take Order Slips and invoke the orderUp() method on them to begin order preparation. • Throughout the day, The waitress’s takeOrder() method, gets parameterized with different order slips from different customers • But she doesn’t confuse! She knows all order slips support orderUp() method and she can call orderUp() anytime she needs a meal prepared!
cook • The Order has all the instructions needed to prepare the meal; the order directs the cook with methods like makeBurger(). • The Short Order Cookhas the knowledge required to prepare the meal. • Waitress and cook are totally decoupled! Waitress has order slips that encapsulate the detail of the meal; she just call a method on each order to get it prepared.
action() Receiver RemoteSlot execute() execute() execute() LightOnCommand GarageDoorOpen StereoOff Now What? Diner to Remote control • We have a waitress that is completely decoupled from the cook by an Order slip, now what? execute(){ receiver.action() } Invoker Command
Light Our first Object! Implementing the Light Public interface Command { public void execute(); } class Light { String name; public void Light(String name){ name = name; } public void on( ) { System.out.println("Light is on "); } public void off( ) { System.out.println("Light is off"); } } On() Off()
LightOnCommand class LightOnCommandimplements Command { private Light myLight; public LightOnCommand ( Light L) { myLight = L; } public void execute( ) { myLight . on( ); } }
Remote Control class SimpleRemoteControl{ private Command slot; public SimpleRemoteControl( Command command) { slot = command; } void onButtonPressed( ) { slot. execute ( ) ; } }
Simple Test Public class RemoteControlTest{ Public static void main(String[] args){ SimpleRemoteControl remote = new SimpleRemoteControl(); Light light = new Light(“Living room”); LightOnCommandlightOn = new LightOnCommand(light); remote.setCommand(lightOn); remote.buttonPressed(); } }
Fan Fan class Fan { String name; public void Fan(String name){ name = name; } public void startRotate() { System.out.println("Fan is rotating"); } public void stopRotate() { System.out.println("Fan is not rotating"); } } startRotate() stopRotate()
FanOnCommand class FanOnCommandimplements Command { private Fan myFan; public FanOnCommand ( Fan F) { myFan = F; } public void execute( ) { myFan . startRotate( ); } }
Simple Test Public class RemoteControlTest{ Public static void main(String[] args){ SimpleRemoteControl remote = new SimpleRemoteControl(); Light light = new Light(“Living room”); LightOnCommandlightOn = new LightOnCommand(light); Fan fan = new Fan(“Bed Room”); FanOnCommandfanOn = new FanOnCommand(fan); remote.setCommand(lightOn); remote.onButtonPressed(); remote.setCommand(fanOn ); remote.onButtonPressed(); } }
Encapsulate a request : by binding together a set of actions on a specific receiver. • Parameterizing an object: by injecting a command object into an invoker. (like a waitress whom is parameterized with multiple orders, or one slot of the remote is parameterized with different requests)
action() Receiver RemoteSlot execute() execute() execute() LightOnCommand GarageDoorOpen StereoOff Command pattern defined execute(){ receiver.action() } Invoker Command
The Invoker parameterized with different lablabalala • تشبیه الجندی مع تعدادی قمبله
Client Invoker Receiver <<Interface>> Command setCommand() action() execute() Class Diagram Public void execute(){ receiver.action(); } ConcreteCommand execute()
Light <<Interface>> Command execute() LightOnCommand LightOffCommand execute() execute() Simple Remote Control RemoteControl SimpleRemoteTest onCommands offCommands setCommand() onButtonPushed() offButtonPushed() on() off()
Back to “Our remote control” • We assign each slot to a command object (so this makes the remote control our Invoker) • We create one lightOnCommand that is bound to the living room object and another is bound to the kitchen light object • When a button is pressed, the execute() method is going to be called on the corresponding command, which results in actions being invoked on the receiver(like lights, ceiling fans, stereos, …)
Undo Commands • How? Who? • Command objects supports undo! • Is – in principle – very easy; just let concrete Command classes implement an undo method, which has the reverse effect of the execute method: public void execute() { light.On(); } public void undo() { light.Off(); } • In remote control, we save the last command, in case of pushing undo button!
Undo a Number of Commands • How? Who? • The specificCommand class knows how to undo an action. • Somebody (Invoker) must keep track of which action to undo… • Queue or what ...? • Yes, Stack
Light <<Interface>> Command execute() undo() LightOnCommand LightOffCommand execute() undo() execute() undo() Simple Remote Control RemoteControl SimpleRemoteTest onCommands offCommands setCommand() onButtonPushed() offButtonPushed() on() off()
Macro command (A sequence of commands) • MacroCommand is a concrete command subclass that simply executes a sequence of commands • • MacroCommandhas no explicit receiver, because the commands it sequences define their own Receiver Command Execute() commands MacroCommand • for all c in commands • c->Execute(); Execute()
Macro Command public class MacroCommand implements Command { Command[] commands; public MacroCommand(Command[] commands) { this.commands = commands; } public void execute() { for (inti = 0; i < commands.length; i++) { commands[i].execute(); } } public void undo() { for (inti = 0; i < commands.length; i++) { commands[i].undo(); } } }
Known Uses: Task Scheduling Service • Generic task scheduling service allow tasks to be scheduled by • Interval (e.g., every hour) • Date/time (e.g., on February 8th at 1:00pm) • Etc. • Tasks are defined using Command objects • Scheduling service executes Command object at the appropriate time, having no idea what it actually does
Task scheduling in java • Executor : An object that executes submitted Runnable tasks. public interface Executor { void execute(Runnable command); } Public interface Runnable { public abstract void run(); }
Logging of commands • Primary application is for crash recovery • Add two new methods Store and Load to the Command interface. • Store: Save the state of the command to disk • Load: Load the state on the command into the command. Calling Execute() will now execute the reestablished command.
Some questions !!! • Who creates a command? • Who invokes a command? • Who executes a command? • Who knows the details of the command? • When should the command be executed? • Who has the knowledge required to carry out the requst? • Should the command return a value?
Example: GUI Toolkit • A GUI toolkit provides a full complement of components • Buttons, scroll bars, text boxes, menus, etc. • Toolkit components know how to draw themselves on the screen, but they don't know how to perform application logic • Application developers need a way to associate application logic with GUI components • What should happen when a button is pressed? • What should happen when a menu item is selected? • GUI components need to perform an unknown operation on an unknown object when they are activated by the user
Menu example Command • Manus can be implemented easily with Command objects • Each choice in a Menu is an instance of a MenuItem class • An Application class creates these menus and their menu items along with the rest of the user interface Application MenuItem Menu Execute() Clicked() command Add(MenuItem) Add(Document) Document(Current) Document Open() Close() Cut() Copy() Paste() command->Execute();
Menu example Command • Command subclasses store the Receiver of the request and invoke one or more specific requests on the Receiver. For example, PasteCommand supports pasting text from the clipboard into a Document • PasteCommand’s Receiver is the Document object it is supplied upon instantiation • The execute operation invokes Paste on the Receiver Document Execute() Document Open() Close() Cut() Copy() Paste() document PasteCommand Execute() document->Paste();
Menu example Command • OpenCommand’s Execute operation: • • Prompts the user for document name • • Creates a corresponding Document’s object • • Adds the document to the Receiver application • • Opens the document Execute() Application application name = AskUse() doc = new Document(name) application->Add(doc) doc->Open() OpenCommand Add(Document) Document(Current) Execute() AskUse()
Command Pattern: Participants • Command • an interface for executing an operation (Do, Execute) • ConcreteCommand (PasteCommand, OpenCommand) • knows its Receiver • implements Execute by invoking the corresponding operation or operations on Receiver • Client (Application) • creates a ConcreteCommand, sets its receiver • Invoker (MenuItem) • requests the Command to execute its operation • Receiver(Document, Application) • knows how to carry out the operations requested from commands. Any class may serve as a Receiver