热门问题
时间线
聊天
视角
命令模式
来自维基百科,自由的百科全书
Remove ads
在物件導向程式設計的範疇中,命令模式(英語:Command pattern),是一種行為型設計模式,它是用來封裝以後某個時間進行的一個動作或觸發一個事件的所有資訊的一個對象。這些資訊包括方法名字,擁有這個方法的對象和給這個方法諸參數的諸值[1]。

概述
使用命令對象,可以更容易的構造以通用構件,用來在其選定的時間,委託、序列或執行方法呼叫,而不需要知道這個方法的類或者這個方法的諸參數。使用呼叫者(invoker)對象,允許方便進行對命令執行的簿記,還有為命令實現不同的模態(mode),這是由呼叫者對象管理的,不需要讓客戶知曉簿記或模態的存在。
這個設計模式的中心想法,是緊密鏡像函數式程式設計語言中的頭等函數和高階函數的語意。尤其呼叫者對象是高階函數,而命令對象是其頭等實際參數。
結構

在上面的UML類圖中,Invoker
類不直接實現一個請求。Invoker
轉而提及到Command
介面,通過它來辦理一個請求(command.execute()
),這使得Invoker
獨立於這些請求的辦理者。Command1
類實現了Command
介面,它在一個接收者(receiver1.action1()
)上施行一個動作。此外,客戶Client
建立具體命令類比如Command1
的對象並設置它的接收者。
UML序列圖展示了執行時互動:Invoker
對象呼叫execute()
於Command1
對象之上。Command1
呼叫action1()
在一個Receiver1
對象之上,它辦理這個請求。
範例
下面是C++例子:
class ICommand {
public:
virtual void Execute() = 0;
};
class Switcher {
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));
Switcher *switcher = new Switcher();
switcher->StoreAndExecute(switchOn);
switcher->StoreAndExecute(switchDown);
delete switcher;
delete switchOn;
delete switchDown;
delete light;
}
Remove ads
下面是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.");
}
}
}
Remove ads
下面是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.");
}
}
}
}
Remove ads
下面是Python例子:
from abc import ABC, abstractmethod
class Light():
def turn_on(self):
print("The light is on")
def turn_off(self):
print("The light is off")
class Command(ABC):
@abstractmethod
def __call__(self): pass
class FlipUpCommand(Command):
def __init__(self, light):
self.__light = light
def __call__(self):
self.__light.turn_on()
class FlipDownCommand(Command):
def __init__(self, light):
self.__light = light
def __call__(self):
self.__light.turn_off()
class Switch():
def __init__(self):
self.history = []
def __call__(self, cmd):
assert isinstance(cmd, Command)
self.history += [type(cmd).__name__]
cmd()
class PressSwitch():
def __init__(self):
lamp = Light()
self.__switch_up = FlipUpCommand(lamp)
self.__switch_down = FlipDownCommand(lamp)
self.__switch = Switch()
def __call__(self, cmd):
cmd = cmd.strip().upper()
if cmd == "ON":
self.__switch(self.__switch_up)
elif cmd == "OFF":
self.__switch(self.__switch_down)
else:
print("Argument 'On' or 'Off' is required.")
其執行:
>>> press_switch = PressSwitch()
>>> press_switch("On")
The light is on
>>> press_switch("Off")
The light is off
>>> press_switch("ThirdState")
Argument 'On' or 'Off' is required.
Remove ads
下面是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);
Remove ads
參照
Wikiwand - on
Seamless Wikipedia browsing. On steroids.
Remove ads