將請求封裝為對象,以便用不同請求參數化客戶;支持請求排隊、記錄日誌、可撤銷操作。
網遊伺服端接收客戶端移動請求:需檢測兩次請求間隔,過短視為外掛——不執行當前請求並回滾上一次。簡化通訊層,核心問題在於如何控制方法執行時機、撤銷與組合。
若在 Man 類中硬編碼判斷邏輯,違反單一職責;且參數、回滾策略(依頻率回滾移動或裝備損耗)會讓類別膨脹。Command 模式將方法提升為類別層次,賦予對時間、撤銷、組合行為的控制力。
using System;
using System.Collections.Generic;
using System.Text;
namespace CommandExample
{
class Program
{
static void Main(string[] args)
{
Man man = new Man();
Server server = new Server();
server.Execute(new MoveForward(man, 10));
System.Threading.Thread.Sleep(50);
server.Execute(new MoveRight(man, 10));
server.Execute(new MoveBackward(man, 10));
server.Execute(new MoveLeft(man, 10));
}
}
class Man
{
int x = 0, y = 0;
public void MoveLeft(int i) => x -= i;
public void MoveRight(int i) => x += i;
public void MoveForward(int i) => y += i;
public void MoveBackward(int i) => y -= i;
public void GetLocation() => Console.WriteLine($"({x},{y})");
}
abstract class GameCommand
{
public DateTime Time { get; set; }
protected Man man;
public Man Man { get => man; set => man = value; }
protected GameCommand(Man man) { Time = DateTime.Now; this.man = man; }
public abstract void Execute();
public abstract void UnExecute();
}
class MoveLeft : GameCommand
{
int step;
public MoveLeft(Man man, int i) : base(man) { step = i; }
public override void Execute() => man.MoveLeft(step);
public override void UnExecute() => man.MoveRight(step);
}
class MoveRight : GameCommand
{
int step;
public MoveRight(Man man, int i) : base(man) { step = i; }
public override void Execute() => man.MoveRight(step);
public override void UnExecute() => man.MoveLeft(step);
}
class MoveForward : GameCommand
{
int step;
public MoveForward(Man man, int i) : base(man) { step = i; }
public override void Execute() => man.MoveForward(step);
public override void UnExecute() => man.MoveBackward(step);
}
class MoveBackward : GameCommand
{
int step;
public MoveBackward(Man man, int i) : base(man) { step = i; }
public override void Execute() => man.MoveBackward(step);
public override void UnExecute() => man.MoveForward(step);
}
class Server
{
GameCommand lastCommand;
public void Execute(GameCommand cmd)
{
Console.WriteLine(cmd.GetType().Name);
if (lastCommand != null && (TimeSpan)(cmd.Time - lastCommand.Time) < TimeSpan.FromMilliseconds(20))
{
Console.WriteLine("Invalid command");
lastCommand.UnExecute();
lastCommand = null;
}
else
{
cmd.Execute();
lastCommand = cmd;
}
cmd.Man.GetLocation();
}
}
}
Execute/UnExecute 介面,記錄時間戳與持有 Receiver。UnExecute 執行反向操作。