[Headfirst Design Mode Study Notes] 6 command mode

Source: Internet
Author: User

Author: gnuhpc
Source: http://www.cnblogs.com/gnuhpc/

1. Our task in this section is to create a universal remote control similar to smart home to control various household appliances. We need to encapsulate the "request" into an object (a command object encapsulates the request by binding a group of actions to a specific receiver ), so that different requests, queues, or logs can be used to parameterize their objects-this is the command mode.

2. Let's look at an example:

First, we need to encapsulate the command object:

Public interface command {
Public void execute ();
}

There is only one method. All the specific command objects must implement this interface, which is encapsulated. For example, for the lamp object,

Public class light {

Public Light (){
}

Public void on (){
System. Out. println ("light is on ");
}

Public void off (){
System. Out. println ("light is off ");
}
}

We can encapsulate the "light on" command through the above interface. This is the so-called command object. It includes the action and receiver into the object and only exposes one execute method:

Public class lightoncommand implements command {
Light light;
Public lightoncommand (light ){
This. Light = light;
}
Public void execute (){
Light. On ();
}
}

Our remote control has nothing to know about the above encapsulation to achieve decoupling:

Public class simpleremotecontrol {
Command slot;
Public simpleremotecontrol (){}
Public void setcommand (command ){
Slot = command;
}
Public void buttonwaspressed (){
Slot.exe cute ();
}
}

Now we try to use this remote control. First we create a remote control, then create the light-on command and place it in it, and then press the button. In this way, the remote control does not know which object it is (actually a light) the request can be sent only when the light is turned on. As a result, the coupling between the remote control and the lamp is very low:

Public class remotecontroltest {
Public static void main (string [] ARGs ){
Simpleremotecontrol remote = new simpleremotecontrol ();
Light = new light ();
Lightoncommand lighton = new lightoncommand (light );
Remote. setcommand (lighton );
Remote. buttonwaspressed ();
}
}

It is very simple. If we want to implement the ability to control multiple appliances in a remote control machine, we can use an array to maintain such a group of commands. It can be seen as a slot that provides multiple commands:

Public class remotecontrol {
Command []Oncommands;
Command []Offcommands;
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;
}
}
Public void setcommand (INT slot, command oncommand, command offcommand ){
Oncommands [Slot] = oncommand;
Offcommands [Slot] = offcommand;
}
Public void onbuttonwaspushed (INT slot ){
Oncommands[slot].exe cute ();
}
Public void offbuttonwaspushed (INT slot ){
Offcommands[slot].exe cute ();
}
Public String tostring (){
}
}

You may notice that a nocommand object appears when initializing the remote control object. This is a little trick. We don't want to check whether a slot is bound with a command every time, So we introduce this stuff to implement a command that does not do anything:

Public class nocommand implements command {
Public void execute (){}
}

In this way, every slot has commands. If the slot of the command is not specified in the future, the default nocommand object is used. This is a typical "null object" example. It is very useful when you do not want to return a meaningful object, this time-space object can be used to determine null or prompt "not bound" information.

3. In the command mode, we can also set Undo-like revocation commands to cancel the issued command request:

Public interface command {
Public void execute ();
Public void undo ();
}

After all, this operation is simple enough: For an on-lamp command, the corresponding undo command is naturally "turn off the light ":

Public class lightoncommand implements command {
Light light;
Public lightoncommand (light ){
This. Light = light;
}
Public void execute (){
Light. On ();
}
Public void undo (){
Light. Off ();
}
}

Although this is simple, it is not complete yet. We must let the remote control remember what was last done before it can be undone:

Package headfirst. Command. Undo;

Import java. util .*;

//
// This is the invoker
//
Public class remotecontrolwithundo {
Command [] oncommands;
Command [] offcommands;
Command undocommand;
Public remotecontrolwithundo (){
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, command offcommand ){
Oncommands [Slot] = oncommand;
Offcommands [Slot] = offcommand;
}
Public void onbuttonwaspushed (INT slot ){
Oncommands[slot].exe cute ();
Undocommand = oncommands [Slot]; // record operation actions
}
Public void offbuttonwaspushed (INT slot ){
Offcommands[slot].exe cute ();
Undocommand = offcommands [Slot]; // record operation actions
}
Public void undobuttonwaspushed (){
Undocommand. Undo (); // issue the undo command
}
Public String tostring (){
}
}

We only have two States for electric lights, but what if there are multiple states? Here is an example of a ceiling fan. The ceiling fan has multiple rotational speeds, high and low levels, and has four statuses:

Public class ceilingfan {
String location = "";
Int level;
Public static final int high = 2;
Public static final int medium = 1;
Public static final int low = 0;
Public ceilingfan (string location ){
This. Location = location;
}
Public void high (){
// Turns the ceiling fan on to high
Level = high;
System. Out. println (location + "ceiling fan is on high ");
}

Public void medium (){
// Turns the ceiling fan on to Medium
Level = medium;
System. Out. println (location + "ceiling fan is on medium ");
}

Public void low (){
// Turns the ceiling fan on to low
Level = low;
System. Out. println (location + "ceiling fan is on low ");
}
Public void off (){
// Turns the ceiling fan off
Level = 0;
System. Out. println (location + "ceiling fan is off ");
}
Public int getspeed (){
Return level;
}
}

When running the fan speed command, record the fan speed before executing the command. The Undo operation is performed according to the recorded part in the command to cancel the command.

Public class ceilingfanhighcommand implements command {
Ceilingfan;
Int prevspeed;

Public ceilingfanhighcommand (ceilingfan ){
This. ceilingfan = ceilingfan;
}
Public void execute (){
Prevspeed = ceilingfan. getspeed ();
Ceilingfan. High ();
}
Public void undo (){
Switch (prevspeed ){
Case ceilingfan. High: ceilingfan. High (); break;
Case ceilingfan. Medium: ceilingfan. Medium (); break;
Case ceilingfan. Low: ceilingfan. Low (); break;
Default: ceilingfan. Off (); break;
}
}
}

Of course, you can also execute multiple commands in batches and complete multiple Undo operations. In this example, you can abstract electric lights and fans into abstract electrical appliances. Then, you can write a command class for general operations on and off two electrical appliances, instead of writing commands for specific electrical appliances such as "electric lights" and "electric fans.

The command mode can be used for work queues and log operations.

 

Author: gnuhpc
Source: http://www.cnblogs.com/gnuhpc/

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.