Skip to content

Files

Latest commit

 

History

History

lesson23

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 

命令模式(Command Pattern)

简介

在面向对象程式设计的范畴中,命令模式是一种设计模式,它尝试以物件来代表实际行动。命令物件可以把行动(action) 及其参数封装起来,于是这些行动可以被:

  • 重复多次
  • 取消(如果该物件有实作的话)
  • 取消后又再重做

这些都是现代大型应用程序所必须的功能,即“复原”及“重复”。除此之外,可以用命令模式来实作的功能例子还有:

  • 交易行为
  • 进度列
  • 精灵
  • 使用者界面按钮及功能表项目
  • 执行绪 pool
  • 宏收录

JavaScript

/* The Invoker function */
var Switch = function(){
    var _commands = [];
    this.storeAndExecute = function(command){
        _commands.push(command);
        command.execute();
    }
}

/* The Receiver function */
var Light = function(){
    this.turnOn = function(){ console.log ('turn on')};
    this.turnOff = function(){ console.log ('turn off') };
}

/* The Command for turning on the light - ConcreteCommand #1 */
var FlipUpCommand = function(light){
    this.execute = light.turnOn;
}

/* The Command for turning off the light - ConcreteCommand #2 */
var FlipDownCommand = function(light){
    this.execute = light.turnOff;
}

var light = new Light();
var switchUp = new FlipUpCommand(light);
var switchDown = new FlipDownCommand(light);
var s = new Switch();

s.storeAndExecute(switchUp);
s.storeAndExecute(switchDown);

Java

import java.util.List;
import java.util.ArrayList;

/* The Command interface */
public interface Command {
   void execute();
}

/* The Invoker class */
public class Switch {
   private List<Command> history = new ArrayList<Command>();

   public Switch() {
   }

   public void storeAndExecute(Command cmd) {
      this.history.add(cmd); // optional 
      cmd.execute();        
   }
}

/* The Receiver class */
public class Light {
   public Light() {
   }

   public void turnOn() {
      System.out.println("The light is on");
   }

   public void turnOff() {
      System.out.println("The light is off");
   }
}

/* The Command for turning on the light - ConcreteCommand #1 */
public class FlipUpCommand implements Command {
   private Light theLight;

   public FlipUpCommand(Light light) {
      this.theLight = light;
   }

   public void execute(){
      theLight.turnOn();
   }
}

/* The Command for turning off the light - ConcreteCommand #2 */
public class FlipDownCommand implements Command {
   private Light theLight;

   public FlipDownCommand(Light light) {
      this.theLight = light;
   }

   public void execute() {
      theLight.turnOff();
   }
}

/* The test class or client */
public class PressSwitch {
   public static void main(String[] args){
      Light lamp = new Light();
      Command switchUp = new FlipUpCommand(lamp);
      Command switchDown = new FlipDownCommand(lamp);

      Switch mySwitch = new Switch();

      try {
         if ("ON".equalsIgnoreCase(args[0])) {
            mySwitch.storeAndExecute(switchUp);
         }
         else if ("OFF".equalsIgnoreCase(args[0])) {
            mySwitch.storeAndExecute(switchDown);
         }
         else {
            System.out.println("Argument \"ON\" or \"OFF\" is required.");
         }
      } catch (Exception e) {
         System.out.println("Arguments required.");
      }
   }
}

实例

模拟烧烤

紧耦合设计

//烤肉串者
public class Barbecuer
{
	//烤羊肉
	public void BakeMutton()
	{
		Console.WriteMutton("烤羊肉串");
	}
	//烤鸡翅
	public void BakeChikenWing()
	{
		Console.WriteMutton("烤鸡翅");
	}
	
}

客户端调用

static void Main(string[] args)
{
	Barbecuer boy = new Barbecuew();
	boy.BakeMutton();
	boy.BakeMutton();
	boy.BakeMutton();
	boy.BakeChickenWing();
}

松耦合设计

抽象命令类

//抽象命令
public abstract class Command
{
	protected Barbecuer receiver;
	
	public Command(Barbecuer receiver)
	{
		this.receiver = receiver;
	}
	
	//执行命令
	abstract public ExcuteCommand();
}

具体命令类

//烤羊肉命令
class BakeMuttonCommand: Command
{
	public BakeMuttonCommand(Barbecuer receiver)
	{
		:base(receiver)
	}
	
	public override void EccuteCommand()
	{
		receiver.BakeMutton();
	}
}

//烤鸡翅命令
class BakeMuttonCommand: Command
{
	public BakeMuttonCommand(Barbecuer receiver)
	{
		:base(receiver)
	}
	
	public override void EccuteCommand()
	{
		receiver.BakeChickenWing();
	}
}

服务员类

//服务员
public class Waiter
{
	private Command command;
	
	//设置订单
	public void setOrder(Command command)
	{
		this.command
	}
	
	//通知执行
	public void Notify()
	{
		command.ExcuteCommand();
	}
}
//烤肉串者
public class Barbecuer
{
	//烤羊肉
	public void BakeMutton()
	{
		Console.WriteMutton("烤羊肉串");
	}
	//烤鸡翅
	public void BakeChikenWing()
	{
		Console.WriteMutton("烤鸡翅");
	}
	
}

客户端实现

static void Main(string[] args)
{
	//开店前的准备
	Barbecuer boy = new Barbecuer();
	Command BakeMuttonCommand1 = new BakeMuttonCommand(boy);
	Command BakeMuttonCommand2 = new BakeMuttonCommand(boy);
	Command BakeChickenWingCommand1 = new BakeMuttonCommand(boy);
	
	Waiter girl = new Waiter();
	
	//开门营业
	girl.SetOrder(BakeMuttonCommand1);
	girl.Notify();

	girl.SetOrder(BakeMuttonCommand2);
	girl.Notify();	
	
	girl.SetOrder(BakeChickenWingCommand1);
	girl.Notify();	
		
	COnsole.Read();
}

松耦合后

//服务员
public class Waiter
{
	private IList<Command> orders = new List<Command>();
	
	//设置订单
	public void SetOrder(Command command)
	{
		if (command.ToString() == "命令模式.BakeChikenWingCommand")
		{
			Console.WriteLine("服务员:鸡翅没有了,请点别的烧烤。");
		} 
		else
		{
			orders.Add(command);
			Console.WriteLine("增加订单:"+ command.ToString() + "时间" + DateTime.Now.ToString());
		}
	}
	
	//取消订单
	public void CancelOrder(Command command)
	{
		orders.Remove(command);
		Console.WriteLine("取消订单" + command.ToString() + "时间" + DateTime.Now.ToString());
	}
	
	//通知全部执行
	public void Notify()
	{
		foreach(Command cmd in orders)
		{
			cmd.ExcuteCommand();
		}
	}
}

客户端代码实现

static void Main(string[] args)
{
	
	Barbecuer boy = new Barbecuer();
	Command BakeMuttonCommand1 = new BakeMuttonCommand(boy);
	Command BakeMuttonCommand2 = new BakeMuttonCommand(boy);
	Command BakeChickenWingCommand1 = new BakeMuttonCommand(boy);
	
	Waiter girl = new Waiter();
	
	girl.setOrder(bakeMuttonCommand1);
	girl.setOrder(bakeMuttonCommand1);
	girl.setOrder(BakeChickenWingCommand1);
	
	girl.Notify();
	
	Console.Read();
}

命令模式:将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数话;对请求排队或者纪录请求日志,以及支持可撤销的操作。

命令模式的优点:

  • 容易地设计一个命令队列。
  • 在需求的情况下,比较容易地将命令记入日志。
  • 允许接受请求的一方决定是否要回绝请求。
  • 很容易对请求撤销或者重做。
  • 加入新的命令类不影响其它的类。
  • 把请求一个操作的对象与知道怎么执行一个操作的对象分割开。