命令模式

物件導向程式設計的範疇中,命令模式(英語:Command pattern)是一種設計模式,它嘗試以物件來代表實際行動。命令物件可以把行動(action) 及其參數封裝起來,於是這些行動可以被:

  • 重複多次
  • 取消(如果該物件有實作的話)
  • 取消後又再重做

這些都是現代大型應用程式所必須的功能,即「復原」及「重複」。除此之外,可以用命令模式來實作的功能例子還有:

  • 交易行為
  • 進度列
  • 精靈
  • 用戶介面按鈕及功能表項目
  • 線程 pool
  • 巨集收錄

結構

 

範例

C#

using System;
using System.Collections.Generic;

namespace CommandPattern
{
    public interface ICommand
    {
        void Execute();
    }

    /* The Invoker class */
    public class Switch
    {
        private List<ICommand> _commands = new List<ICommand>();

        public void StoreAndExecute(ICommand command)
        {
            _commands.Add(command);
            command.Execute();
        }
    }

    /* The Receiver class */
    public class Light
    {
        public void TurnOn()
        {
            Console.WriteLine("The light is on");
        }

        public void TurnOff()
        {
            Console.WriteLine("The light is off");
        }
    }

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

        public FlipUpCommand(Light light)
        {
            _light = light;
        }

        public void Execute()
        {
            _light.TurnOn();
        }
    }

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

        public FlipDownCommand(Light light)
        {
            _light = light;
        }

        public void Execute()
        {
            _light.TurnOff();
        }
    }

    /* The test class or client */
    internal class Program
    {
        public static void Main(string[] args)
        {
            Light lamp = new Light();
            ICommand switchUp = new FlipUpCommand(lamp);
            ICommand switchDown = new FlipDownCommand(lamp);

            Switch s = new Switch();
            string arg = args.Length > 0 ? args[0].ToUpper() : null;
            if (arg == "ON")
            {
                s.StoreAndExecute(switchUp);
            }
            else if (arg == "OFF")
            {
                s.StoreAndExecute(switchDown);
            }
            else
            {
                Console.WriteLine("Argument \"ON\" or \"OFF\" is required.");
            }
        }
    }
}

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.");
      }
   }
}

Python

class Switch(object):
    """The INVOKER class"""
    def __init__(self, flip_up_cmd, flip_down_cmd):
        self.flip_up = flip_up_cmd
        self.flip_down = flip_down_cmd

class Light(object):
    """The RECEIVER class"""
    def turn_on(self):
        print("The light is on")
    def turn_off(self):
        print("The light is off")

class LightSwitch(object):
    """The CLIENT class"""
    def __init__(self):
        lamp = Light()
        self._switch = Switch(lamp.turn_on, lamp.turn_off)

    def switch(self, cmd):
        cmd = cmd.strip().upper()
        if cmd == "ON":
            self._switch.flip_up()
        elif cmd == "OFF":
            self._switch.flip_down()
        else:
            print("Argument 'ON' or 'OFF' is required.")

# Execute if this file is run as a script and not imported as a module
if __name__ == "__main__":
    light_switch = LightSwitch()
    print("Switch ON test.")
    light_switch.switch("ON")
    print("Switch OFF test.")
    light_switch.switch("OFF")
    print("Invalid Command test.")
    light_switch.switch("****")

Scala

/* The Command interface */
trait Command {
   def execute()
}
 
/* The Invoker class */
class Switch {
   private var history: List[Command] = Nil
 
   def storeAndExecute(cmd: Command) {
      cmd.execute()
      this.history :+= cmd
   }
}
 
/* The Receiver class */
class Light {
   def turnOn() = println("The light is on")
   def turnOff() = println("The light is off")
}
 
/* The Command for turning on the light - ConcreteCommand #1 */
class FlipUpCommand(theLight: Light) extends Command {
   def execute() = theLight.turnOn()
}
 
/* The Command for turning off the light - ConcreteCommand #2 */
class FlipDownCommand(theLight: Light) extends Command {
   def execute() = theLight.turnOff()
}
 
/* The test class or client */
object PressSwitch {
   def main(args: Array[String]) {
      val lamp = new Light()
      val switchUp = new FlipUpCommand(lamp)
      val switchDown = new FlipDownCommand(lamp)
 
      val s = new Switch()
 
      try {
         args(0).toUpperCase match {
            case "ON" => s.storeAndExecute(switchUp)
            case "OFF" => s.storeAndExecute(switchDown)
            case _ => println("Argument \"ON\" or \"OFF\" is required.")
         }
      } catch {
         case e: Exception => println("Arguments required.")
      }
   }
}

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);


C++

class ICommand
{
    public:
        virtual void Execute() = 0;
};

class Swicher
{
    private:
      std::vector<ICommand *> _commands;

    public:
        void StoreAndExecute(ICommand *command)
        {
            if (command){
                _commands.push_back(command);
                command->Execute();
            }
        }
};

class Light
{
    public:
        void TurnOn()
        {
            std::cout<<"The light is on."<<std::endl;
        }

        void TurnOff()
        {
            std::cout << "The light is off." << std::endl;
        }
};

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

  public:
    FlipUpCommand(Light *light)
    {
        _light = light;
    }

    void Execute()
    {
        _light->TurnOn();
    }
};

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

  public:
    FlipDownCommand(Light *light)
    {
        _light = light;
    }

    void Execute()
    {
        _light->TurnOff();
    }
};

int main()
{
    Light *light = new Light();
    ICommand *switchOn = dynamic_cast<ICommand *>(new FlipUpCommand(light));
    ICommand *switchDown = dynamic_cast<ICommand *>(new FlipDownCommand(light));

    Swicher *switcher = new Swicher();
    switcher->StoreAndExecute(switchOn);
    switcher->StoreAndExecute(switchDown);

    delete switcher;
    delete switchOn;
    delete switchDown;
    delete light;
}