命令模式(Command Pattern)

Posted 街酒

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了命令模式(Command Pattern)相关的知识,希望对你有一定的参考价值。

命令模式,每个命令代表一个接收者

一、模式动机

命令模式(Command Pattern)是一种常用的行为型设计模式,它将请求发送者与请求接收者解耦,请求发送者通过命令对象来间接引用接收者,使得系统具有更好的灵活性,可以在不修改现有系统源代码的情况下将相同的发送者对应不同的接收者,也可以将多个命令对象组合成宏命令,还可以在命令类中提供用来撤销请求的方法。
命令模式又称为“动作(Action)模式”或者“事务(Transaction)模式”,是对象行为型模式之一。

  • 现实生活
    • 相同的开关可以通过不同的电线来控制不同的电器
    • 开关 类比 请求发送者
    • 电灯 类比 请求的最终接收者和处理者
    • 开关和电灯之间并不存在直接耦合关系,它们通过电线连接在一起,使用不同的电线可以连接不同的请求接收者
  • 软件开发
    • 按钮 相当于 请求发送者
    • 事件处理类 相当于 请求的最终接收者和处理者
    • 发送者与接收者之间引入了新的命令对象(类似电线),将发送者的请求封装在命令对象中,再通过命令对象来调用接收者的方法
    • 相同的按钮可以对应不同的事件处理类
    • 将请求发送者和接收者完全解耦
    • 发送者与接收者之间没有直接引用关系
    • 发送请求的对象只需要知道如何发送请求,而不必知道如何完成请求

二、模式定义

  • 命令模式(Command Pattern):将一个请求封装为一个对象,从而使我们可用不同的请求对客户进行参数化;对请求排队或者记录请求日志,以及支持可撤销的操作
  • 命令模式是一种对象行为型模式,其别名为动作(Action)模式或事务(Transaction)模式
    • “用不同的请求对客户进行参数化”
    • “对请求排队”
    • “记录请求日志”
    • “支持可撤销操作”

三、模式结构

四、案例实现

案例背景

电视机遥控器

案例结构

代码实现

电视机类

public class Television 

    public void open()
        System.out.println("打开电视");
    
    public void close()
        System.out.println("关闭");
    
    public void change()
        System.out.println("换台");
    


抽象命令类

public interface Command 

    void excute();


打开命令

public class OpenCommand implements Command

    private Television t;

    public OpenCommand()
        t = new Television();
    

    @Override
    public void excute() 
        t.open();
    

关闭命令

public class CloseCommand implements Command

    private Television t;

    public CloseCommand() 
        t = new Television();
    

    @Override
    public void excute() 
        t.close();
    

换台命令

public class ChangeCommand implements Command

    private Television t;

    public ChangeCommand() 
        t = new Television();
    

    @Override
    public void excute() 
        t.change();
    

电视机遥控器

public class Controller 

    private Command openCommand,closeCommand,changeCommand;

    public Controller(Command openCommand, Command closeCommand, Command changeCommand) 
        this.openCommand = openCommand;
        this.closeCommand = closeCommand;
        this.changeCommand = changeCommand;
    

    public void open()
        openCommand.excute();
    

    public void close()
        closeCommand.excute();
    
    public void change()
        changeCommand.excute();
    

客户类

public class Client 

    public static void main(String[] args) 
        Command openCommand,closeCommand,changeCommand;
        openCommand = new OpenCommand();
        closeCommand = new CloseCommand();
        changeCommand = new ChangeCommand();
        Controller controller = new Controller(openCommand,closeCommand,changeCommand);
        controller.open();
        controller.close();
        controller.change();
    


案例结果

案例分析

调用者与抽象命令相关联,在程序运行时注入具体命令类对象,在Controller的业务方法中调用命令类的excute(),不同命令类的excute()不同,可以调用请求接受者的不同请求响应方法。
每一个具体命令类对应一个请求的处理者(接收者),通过向请求发送者注入不同的具体命令对象可以使相同的发送者对应不同的接收者,从而实现“将一个请求封装为一个对象,用不同的请求对客户进行参数化”,客户端只需要将具体命令对象作为参数注入请求发送者,无须直接操作请求的接收者

五、模式分析

  • 命令模式的本质是对请求进行封装
  • 将请求发送者和接收者完全解耦
  • 使得请求的一方不必知道接收请求的一方的接口,更不必知道请求如何被接收、操作是否被执行、何时被执行,以及是怎么被执行的。
  • 发送请求的对象只需要知道如何发送请求,而不必知道如何完成请求
  • 命令模式的本质是对请求进行封装
  • 一个请求对应于一个命令,将发出命令的责任和执行命令的责任分开

六、总结

模式优点

  • 降低系统的耦合度
  • 新的命令可以很容易地加入到系统中,符合开闭原则
  • 可以比较容易地设计一个命令队列或宏命令(组合命令)
  • 为请求的撤销(Undo)和恢复(Redo)操作提供了一种设计和实现方案

模式缺点

  • 使用命令模式可能会导致某些系统有过多的具体命令类(针对每一个对请求接收者的调用操作都需要设计一个具体命令类)

使用情形

  • 需要将请求调用者和请求接收者解耦,使得调用者和接收者不直接交互
  • 需要在不同的时间指定请求、将请求排队和执行请求
  • 需要支持命令的撤销(Undo)操作和恢复(Redo)操作
  • 需要将一组操作组合在一起形成宏命令

设计模式 - 命令模式(command pattern) 具体解释

命令模式(command pattern) 详细解释


本文地址: http://blog.csdn.net/caroline_wendy


命令模式: 将请求封装成对象, 以便使用不同的请求\队列\日志来參数化其它对象. 命令模式也支持可撤销操作.


命令模式:

调用者(Invoker);

命令(Command): 可运行方法(execute), 详细命令(Concrete Command);

接受者(Receiver): 调用命令(Set Command);


详细方法:

1. 详细对象.

/**
 * @time 2014年6月9日
 */
package command;

/**
 * @author C.L.Wang
 *
 */
public class Light {

	public Light() {}
	
	public void on() {
		System.out.println("Light is on");
	}
	
	public void off() {
		System.out.println("Light is off");
	}
	
}


/**
 * @time 2014年6月9日
 */
package command;

/**
 * @author C.L.Wang
 *
 */
public class GarageDoor {
	
	public GarageDoor() {}

	public void up() {
		System.out.println("Garage Door is Open");
	}

	public void down() {
		System.out.println("Garage Door is Closed");
	}

	public void stop() {
		System.out.println("Garage Door is Stopped");
	}

	public void lightOn() {
		System.out.println("Garage light is on");
	}

	public void lightOff() {
		System.out.println("Garage light is off");
	}
}

2. 命令接口(command interface), 包括运行方法execute().

/**
 * @time 2014年6月9日
 */
package command;

/**
 * @author C.L.Wang
 *
 */
public interface Command {
	public void execute();
}


3. 详细命令(concrete command), 继承命令接口, 实现接口的方法.

/**
 * @time 2014年6月9日
 */
package command;

/**
 * @author C.L.Wang
 *
 */
public class LightOnCommand implements Command {

	Light light;
	
	public LightOnCommand (Light light) {
		this.light = light;
	}
	
	/* (non-Javadoc)
	 * @see command.Command#execute()
	 */
	@Override
	public void execute() {
		// TODO Auto-generated method stub
		light.on();
	}

}



/**
 * @time 2014年6月9日
 */
package command;

/**
 * @author C.L.Wang
 *
 */
public class GarageDoorOpenCommand implements Command {
	
	GarageDoor garageDoor;
	
	public GarageDoorOpenCommand (GarageDoor garageDoor) {
		this.garageDoor = garageDoor;
	}
	
	/* (non-Javadoc)
	 * @see command.Command#execute()
	 */
	@Override
	public void execute() {
		// TODO Auto-generated method stub
		garageDoor.up();
	}

}

4. 接受者(receiver), 通过传递的命令參数, 调用运行方法.

/**
 * @time 2014年6月9日
 */
package command;

/**
 * @author C.L.Wang
 *
 */
public class SimpleRemoteControl {
	
	Command slot;
	
	public SimpleRemoteControl() {}
	
	public void setCommand(Command command) {
		this.slot = command;
	}
	
	public void buttonWasPressed() {
		slot.execute();
	}
}

5. 測试, 创建接收者, 创建对象, 将对象传递至命令, 接受者调用命令, 运行.

/**
 * @time 2014年6月9日
 */
package command;

/**
 * @author C.L.Wang
 *
 */
public class RemoteControlTest {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		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();
		
	}

}


技术分享





以上是关于命令模式(Command Pattern)的主要内容,如果未能解决你的问题,请参考以下文章

[Design Pattern] Command Pattern 简单案例

设计模式 - 命令模式(command pattern) 具体解释

命令模式(Command Pattern)

设计模式----行为型模式之命令模式(Command Pattern)

命令模式(Command Pattern)

命令模式(Command Pattern)