2013年7月20日 星期六

設計模式:命令模式 (Command Pattern)

命令模式 (Command Pattern),以下程式碼以 C# 為例

說明:
命令包含發出命令和執行命令。
命令模式,則是將這個過程拆成三個物件,
發出命令的物件(Invoker)、命令的物件(command)、執行命令的物件(receiver)
由 Invoker 物件,來建造要執行的命令。
如此要擴充功能時,例如增加命令重覆執行、取消命令...等,也變得較單純。

範例:
有一個機器人物件,會執行三種指令:向前走一步、向左轉、向右轉。

希望達成如下的效果
static void Main(string[] args)
{
    // 初始化各個物件
    Invoker invoker = new Invoker(); // 發命令物件

    ReceiverRobot robot = new ReceiverRobot(); // 執行命令物件

    GoAheadCommand cmd_go_ahead = new GoAheadCommand(robot); // 向前走指令
    TurnLeftCommand cmd_turn_left = new TurnLeftCommand(robot); // 左轉指令
    TurnRightCommand cmd_turn_right = new TurnRightCommand(robot); // 右轉指令

    // 設定要執行的命令
    invoker.SetCommand(cmd_go_ahead);
    invoker.SetCommand(cmd_go_ahead);
    invoker.SetCommand(cmd_turn_left);
    invoker.SetCommand(cmd_go_ahead);
    invoker.SetCommand(cmd_turn_right);

    // 開始執行命令
    invoker.Run();

    Console.Read();
}
執行結果: 
向前走一步
向前走一步
向左轉
向前走一步
向右轉

實現重點在於,分成發命令物件、命令物件、執行命令的物件。
發命令物件:可用來新增要執行命令。
命令物件:可指定執行此命令的物件。
執行命令的物件:真正執行此命令的物件。

其餘程式碼
// 用來發出命令的類別
class Invoker
{
    private IList<Command> cmds = new List<Command>();

    public void SetCommand(Command command)
    {
        cmds.Add(command);
    }

    public void Run()
    {
        foreach (Command command in cmds)
        {
            command.Execute();
        }
    }

}

// 命令的抽像類別,用來衍生各種命令,建構時,須設定實際執行命令的物件
abstract class Command
{
    protected ReceiverRobot robot;

    // 設定實際執行命令的物件
    public Command(ReceiverRobot robot)
    {
        this.robot = robot;
    }

    // 用來呼叫執行命令的物件,開始執行命令
    abstract public void Execute();
}

// 向前走一步的命令
class GoAheadCommand : Command
{
    public GoAheadCommand(ReceiverRobot robot)
        : base(robot)
    {
    }

    public override void Execute()
    {
        robot.GoAhead();
    }
}

// 向左轉的命令
class TurnLeftCommand : Command
{
    public TurnLeftCommand(ReceiverRobot robot)
        : base(robot)
    {
    }

    public override void Execute()
    {
        robot.TurnLeft();
    }
}

// 向右轉的命令
class TurnRightCommand : Command
{
    public TurnRightCommand(ReceiverRobot robot)
        : base(robot)
    {
    }

    public override void Execute()
    {
        robot.TurnRight();
    }
}

// 實際執行命令的物件
class ReceiverRobot
{
    public void GoAhead()
    {
        Console.WriteLine("向前走一步");
    }

    public void TurnLeft()
    {
        Console.WriteLine("向左轉");
    }

    public void TurnRight()
    {
        Console.WriteLine("向右轉");
    }
}

相關連結:設計模式整理列表

沒有留言:

張貼留言