19. Command

Keywords: Programming

Command pattern: Encapsulating a request as an object allows us to parameterize customers with different requests; queuing or logging requests; and supporting revocable operations. Command mode is an object behavioral mode, which is aliased as Action mode or Transaction mode.

Command mode includes the following roles:

Command (abstract command class): An Abstract command class is generally an abstract class or interface in which methods such as execute() for executing requests are declared, through which the relevant operations of the requester can be invoked.
ConcreteCommand (Specific Command Class): Specific command class is a subclass of abstract command class, which implements the method declared in abstract command class. It corresponds to specific recipient object and binds the actions of recipient object to it. When the execute() method is implemented, the action of the recipient object is invoked.
Invoker: The caller is the sender of the request, which executes the request through the command object. A caller does not need to identify its receiver at design time, so it only has an association with abstract command classes. When the program runs, a specific command object can be injected into it, and then the execute() method of the specific command object can be invoked, so as to indirectly invoke the related operations of the requester and receiver.
Receiver (Receiver): The receiver performs the operation related to the request, which specifically implements the business processing of the request.

1. Main Advantages

(1) Reduce the coupling degree of the system. Because there is no direct reference between the requester and the receiver, the requester and the receiver are completely decoupled. The same requester can correspond to different receivers. Similarly, the same receiver can also be used by different requesters. There is good independence between the two.
(2) New commands can be easily added to the system. Since adding new specific command classes will not affect other classes, it is easy to add new specific command classes without modifying the original system source code, or even the client class code, to meet the requirements of the "Open-Close Principle".
(3) It is easy to design a command queue or macro command (combination command).
(4) It provides a design and implementation scheme for Undo and Redo operations of requests.

2. Main shortcomings

Using command mode may result in too many specific command classes in some systems. Because a specific command class needs to be designed for each invocation operation to the request recipient, a large number of specific command classes may need to be provided in some systems, which will affect the use of command mode.

3. Applicable Scenario

(1) The system needs to decouple the requester and the requester so that the caller and the receiver do not interact directly. Request caller does not need to know the existence of the recipient, who the recipient is, and when the recipient is called.
(2) The system needs to specify, queue and execute requests at different times. A command object and the initial caller of a request can have different life cycles. In other words, the original requester may be no longer there, and the command object itself is still active. The requester can be invoked through the command object without concern for the existence of the requester, and can be realized through the mechanism of request log file.
(3) The system needs to support command Undo and Redo operations.
(4) The system needs to combine a group of operations to form macro commands.

Command Patterns in King's Glory (Release, Cancel Skills):

/**
 * 2018/12/6
 * Command
 *
 * @author machuanpeng
 */
public interface Command {
	public void execute();
}
/**
 * 2018/12/6
 * Release skill command
 *
 * @author machuanpeng
 */
public class ReleaseSkillCommand implements Command {  
  
    private LuBanReceiver receiver;  
      
    public ReleaseSkillCommand(LuBanReceiver receiver) {  
        this.receiver = receiver;  
    }  
  
    @Override  
    public void execute() {  
        receiver.releaseSkill();  
    }  
}
/**
 * 2018/12/6
 * Cancellation of skill orders
 *
 * @author machuanpeng
 */
public class RetreatCommand implements Command {  
  
    private LuBanReceiver receiver;  
      
    public RetreatCommand(LuBanReceiver receiver) {  
        this.receiver = receiver;  
    }  
  
    @Override  
    public void execute() {  
        receiver.retreatOpration();  
    }  
}
/**
 * 2018/12/6
 * Callee (Luban)
 *
 * @author machuanpeng
 */
public class LuBanReceiver {  
    
    public void releaseSkill(){  
        System.out.println("Release Skills Animation");  
    } 
    
    public void retreatOpration(){  
        System.out.println("Cancel Skill Animation");  
    }  
}
/**
 * 2018/12/6
 * Summoner
 *
 * @author machuanpeng
 */
public class SummonerInvoker {  
    
    private List<Command> commands = new ArrayList<Command>();

    public void addOpration(Command command){  
        commands.add(command);  
    }  
    
    public void removeOpration(Command command){  
        commands.remove(command);  
    } 
    
	public void notify() {
		for(Command command:commands) {
			command.execute();
		}
    } 
}

Test:

public class Client {
	public static void main(String args[]) {
        LuBanReceiver receiver = new LuBanReceiver();
		Command releaseSkill = new ReleaseSkillCommand(receiver);
        Command retreatCommand = new RetreatCommand(receiver);
        SummonerInvoker invoker = new SummonerInvoker();
        invoker.addOpration(releaseSkill);
        invoker.addOpration(retreatCommand);
        invoker.notify();
	}
}

Posted by lucym on Thu, 10 Oct 2019 05:53:44 -0700