Design mode - command mode

Smart Life project requirements

  1. We bought a set of smart appliances, including lights, fans, refrigerators and washing machines. We can control the work of these appliances as long as we install apps on our mobile phones.
  2. These smart appliances come from different manufacturers. We don't want to install an app for each kind of home appliance and control them separately. We hope that only one app can control all smart appliances.
  3. To realize the need for an app to control all smart appliances, each smart appliance manufacturer should provide a unified interface for app calls. At this time, the command mode can be considered.
  4. Command mode decouples the action requester from the action performer object
  5. In our example, the requester of the action is a mobile app, and the executor of the action is a household appliance of each manufacturer

Command mode

Basic introduction

  1. Command Pattern: in software design, we often need to send requests to some objects, but we don't know who the receiver of the request is or what the requested operation is. We just need to specify the specific receiver of the request when the program is running. At this time, we can use the Command Pattern for design
  2. The naming pattern makes the request sender and the request receiver eliminate the coupling between each other, makes the call relationship between objects more flexible and realizes decoupling.
  3. In the naming mode, a request is encapsulated into an object to represent different requests (i.e. naming) with different parameters. At the same time, the command mode also supports revocable operations.
  4. The general gives orders and the soldiers carry them out. There are several roles: General (the order issuer), soldier (the specific executor of the order), and Command (connecting general and soldier). Invoker is the caller (general), Receiver is the callee (soldier), and MyCommand is the Command. It implements the Command interface and holds the receiving object

Schematic class diagram

  • Invoker is the caller role
  • Command: is a command role. All commands to be executed are here. They can be interfaces or abstract classes
  • Receiver: the receiver role, which knows how to implement and execute a request related operation
  • ConcreteCommand: bind a receiver object to an action, call the corresponding operation of the receiver, and implement execute

Command mode to solve intelligent life project

Train of thought analysis and illustration

package com.atguigu.command;


//Create command interface
public interface Command {

	//Execute action (operation)
	public void execute();
	//Undo action
	public void undo();
}
package com.atguigu.command;

public class LightOnCommand implements Command {

	//Aggregate LightReceiver
	
	LightReceiver light;
	
	//constructor 
	public LightOnCommand(LightReceiver light) {
		super();
		this.light = light;
	}
	
	@Override
	public void execute() {
		// TODO Auto-generated method stub
		//Call the recipient's method
		light.on();
	}

	

	@Override
	public void undo() {
		// TODO Auto-generated method stub
		//Call the recipient's method
		light.off();
	}

}
package com.atguigu.command;

public class LightOffCommand implements Command {

	// Aggregate LightReceiver

	LightReceiver light;

	// constructor 
	public LightOffCommand(LightReceiver light) {
			super();
			this.light = light;
		}

	@Override
	public void execute() {
		// TODO Auto-generated method stub
		// Call the recipient's method
		light.off();
	}

	@Override
	public void undo() {
		// TODO Auto-generated method stub
		// Call the recipient's method
		light.on();
	}
}
package com.atguigu.command;

/**
 * No command, i.e. empty execution: used to initialize each button. When the empty command is called, the object does nothing
 * In fact, this is a design mode, which can eliminate the judgment of air
 * @author Administrator
 *
 */
public class NoCommand implements Command {

	@Override
	public void execute() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void undo() {
		// TODO Auto-generated method stub
		
	}

}
package com.atguigu.command;

public class LightReceiver {

	public void on() {
		System.out.println(" The light is on.. ");
	}
	
	public void off() {
		System.out.println(" The lights are off.. ");
	}
}
package com.atguigu.command;

public class TVOnCommand implements Command {

	// Aggregate TVReceiver

	TVReceiver tv;

	// constructor 
	public TVOnCommand(TVReceiver tv) {
		super();
		this.tv = tv;
	}

	@Override
	public void execute() {
		// TODO Auto-generated method stub
		// Call the recipient's method
		tv.on();
	}

	@Override
	public void undo() {
		// TODO Auto-generated method stub
		// Call the recipient's method
		tv.off();
	}
}
package com.atguigu.command;

public class TVOffCommand implements Command {

	// Aggregate TVReceiver

	TVReceiver tv;

	// constructor 
	public TVOffCommand(TVReceiver tv) {
		super();
		this.tv = tv;
	}

	@Override
	public void execute() {
		// TODO Auto-generated method stub
		// Call the recipient's method
		tv.off();
	}

	@Override
	public void undo() {
		// TODO Auto-generated method stub
		// Call the recipient's method
		tv.on();
	}
}
package com.atguigu.command;

public class TVReceiver {
	
	public void on() {
		System.out.println(" The TV is on.. ");
	}
	
	public void off() {
		System.out.println(" The TV is off.. ");
	}
}
package com.atguigu.command;

public class RemoteController {

	// Command array of on button
	Command[] onCommands;
	Command[] offCommands;

	// Execute undo command
	Command undoCommand;

	// Constructor to complete the initialization of the button

	public RemoteController() {

		onCommands = new Command[5];
		offCommands = new Command[5];

		for (int i = 0; i < 5; i++) {
			onCommands[i] = new NoCommand();
			offCommands[i] = new NoCommand();
		}
	}

	// Give our buttons the commands you need
	public void setCommand(int no, Command onCommand, Command offCommand) {
		onCommands[no] = onCommand;
		offCommands[no] = offCommand;
	}

	// Press the on button
	public void onButtonWasPushed(int no) { // no 0
		// Find the on button you pressed and call the corresponding method
		onCommands[no].execute();
		// Record this operation for cancellation
		undoCommand = onCommands[no];

	}

	// Press the on button
	public void offButtonWasPushed(int no) { // no 0
		// Find the off button you pressed and call the corresponding method
		offCommands[no].execute();
		// Record this operation for cancellation
		undoCommand = offCommands[no];

	}
	
	// Press the undo button
	public void undoButtonWasPushed() {
		undoCommand.undo();
	}

}
package com.atguigu.command;

public class Client {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		
		//Use the command design mode to complete the operation of the electric lamp through the remote control
		
		//Create the object of the light (receiver)
		LightReceiver lightReceiver = new LightReceiver();
		
		//Create light related switch commands
		LightOnCommand lightOnCommand = new LightOnCommand(lightReceiver);
		LightOffCommand lightOffCommand = new LightOffCommand(lightReceiver);
		
		//Need a remote control
		RemoteController remoteController = new RemoteController();
		
		//Set commands for our remote control, such as no = 0, which is the operation of turning on and off the electric light
		remoteController.setCommand(0, lightOnCommand, lightOffCommand);
		
		System.out.println("--------Press the on button of the light-----------");
		remoteController.onButtonWasPushed(0);
		System.out.println("--------Press the light off button-----------");
		remoteController.offButtonWasPushed(0);
		System.out.println("--------Press the undo button-----------");
		remoteController.undoButtonWasPushed();
		
		
		System.out.println("=========Operate the TV with the remote control==========");
		
		TVReceiver tvReceiver = new TVReceiver();
		
		TVOffCommand tvOffCommand = new TVOffCommand(tvReceiver);
		TVOnCommand tvOnCommand = new TVOnCommand(tvReceiver);
		
		//Set commands for our remote control, such as no = 1, which is the operation of turning on and off the TV
		remoteController.setCommand(1, tvOnCommand, tvOffCommand);
		
		System.out.println("--------Press the on button on the TV-----------");
		remoteController.onButtonWasPushed(1);
		System.out.println("--------Press the off button on the TV-----------");
		remoteController.offButtonWasPushed(1);
		System.out.println("--------Press the undo button-----------");
		remoteController.undoButtonWasPushed();

	}

}

Precautions and details of command mode

  1. Decouple the object that initiates the request from the object that executes the request. The object initiating the request is the caller. The caller can let the receiver work as long as he calls the execute() method of the command object, without knowing who the specific receiver object is and how to implement it. The command object will be responsible for letting the receiver execute the requested action, In other words, the decoupling between "request initiator" and "request executor" is realized through the command object, which acts as a bridge.
  2. Easy to design a command queue. As long as the command object is queued, the command can be executed in multiple threads
  3. It is easy to undo and redo the request
  4. Insufficient command mode: some systems may have too many specific command classes, increasing the complexity of the system, which should be paid attention to when using
  5. Empty command is also a design mode, which saves us the operation of judging empty. In the above example, if we don't use the empty command, we will judge it empty every time we press a key, which brings us some trouble in coding.
  6. The classic application scenario of command mode: a button on the interface is a command, simulating the cancellation / recovery of CMD (DOS command) order and trigger feedback mechanism

Keywords: Design Pattern

Added by ldb358 on Mon, 07 Feb 2022 15:08:05 +0200