命令模式 The Command Pattern

本文介绍如何将命令模式与观察者模式相结合,通过具体的代码示例展示如何利用这两种设计模式来组织和管理对象之间的交互。实现了命令的发布与执行,并支持撤销操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

命令模式——“请求”封装成对象,以便使用不同的请求,队列或者日志来参数化其它对象。命令模式也支持可撤消的操作。(摘自《Head First Design Patterns》)
以下是自已用VS画了一个简图:
创建命令接口:
interface ICommand

    {

        void Execute();



        void Undo();

    }
实现三个命令:
class AttackCommand : ICommand

    {

        #region Command 成员



        public void Execute()

        {

            Console.WriteLine("攻击");

        }



        public void Undo()

        {

            Console.WriteLine("撤消攻击");

        }



        #endregion

    }

class RetreatCommand : ICommand

    {

        #region Command 成员



        public void Execute()

        {

            Console.WriteLine("撤退");

        }



        public void Undo()

        {

            Console.WriteLine("撤消撤退");

        }



        #endregion

    }



class NoCommand : ICommand

    {

        #region ICommand 成员



        public void Execute()

        {

            

        }



        public void Undo()

        {

            

        }



        #endregion

    }
其中空命令为了初始化使用,不必判断NULL了。创建一个司令官,用来发布命令:
class Commander

    {

        private ICommand UndoCommand = new NoCommand();

    

        public void SetCommand(ICommand command)

        {

            command.Execute();

            UndoCommand = command;

        }



        public void UndoLastCommand()

        {

            UndoCommand.Undo();

            UndoCommand = new NoCommand();

        }

    }
测试一下:
Commander commander = new Commander();

            AttackCommand attackCommand = new AttackCommand();

            RetreatCommand retreatCommand = new RetreatCommand();

            commander.SetCommand(attackCommand);

            commander.UndoLastCommand();

            commander.SetCommand(retreatCommand);

            commander.UndoLastCommand();

            commander.SetCommand(attackCommand);

            commander.SetCommand(retreatCommand);

            commander.UndoLastCommand();

            commander.UndoLastCommand();//程序只实了一次撤消,因此这里的第二次撤消没有作用,用户可以创建撤消命令数组来存储实现多次撤消。
输出结果:
攻击
撤消攻击
撤退
撤消撤退
攻击
撤退
撤消撤退
在以前的观察者模式中,使用了发布命令,但是没用应用命令模式,现在结合命令模式重新改写一下以前的观察者模式:
下面是用VS画的一个简图:
其中原本用的接口改成了抽象类,为了简化一下代码,这里主要是为了我自己的这个例子。
/// <summary>

    /// 主题对象接口

    /// </summary>

    public interface ISubject

    {

        List<Observer> Observers

        {

            get;

            set;

        }



        void RegisterObserver(Observer observer);



        void RemoveObserver(Observer observer);



        void NotifyObservers();

    }



/// <summary>

    /// 观察者基类

    /// </summary>

    public abstract class Observer

    {

        public abstract void Update(Command command);



        #region = Name =



        private string _name;



        public string Name

        {

            get { return _name; }

            set { _name = value; }

        }



        #endregion



        #region = AttackSlogan =



        private string _attackslogan;



        public string AttackSlogan

        {

            get { return _attackslogan; }

            set { _attackslogan = value; }

        }



        #endregion



        #region = RetreatSlogan =



        private string _retreatslogan;



        public string RetreatSlogan

        {

            get { return _retreatslogan; }

            set { _retreatslogan = value; }

        }



        #endregion

    }



/// <summary>

    /// 斧头小队--观察者

    /// </summary>

    public class AxeTeam : Observer 

    {

        #region Observer 成员

        



        public AxeTeam()

        {

            this.Name = "斧头小队";

            this.AttackSlogan = "用斧头攻击,势死如归!";

            this.RetreatSlogan = "坚守阵地,死也不放弃!";

        }



        public override void Update(Command command)

        {

            command.Observer = this;

            command.Execute();

        }



        #endregion

    }



/// <summary>

    /// 弓箭手小队--观察者

    /// </summary>

    public class BowAndArrowTeam : Observer 

    {

        #region Observer 成员

     



        public BowAndArrowTeam()

        {

            this.Name = "弓箭手小队";

            this.AttackSlogan = "弓箭手掩护,退后十步,射箭!";

            this.RetreatSlogan = "边撤退,边掩护斧头小队!";

        }



        public override void Update(Command command)

        {

            command.Observer = this;

            command.Execute();

        }



        #endregion

    }



/// <summary>

    /// 匕首小队--观察者

    /// </summary>

    public class KnifeTeam : Observer

    {

        #region Observer 成员



       



        public KnifeTeam()

        {

            this.Name = "匕首小队";

            this.AttackSlogan = "匕首攻击,打不过就跑!";

            this.RetreatSlogan = "快撤啊,我军大势已去!";

        }



        public override void Update(Command command)

        {

            command.Observer = this;

            command.Execute();

        }



        #endregion

    }



/// <summary>

    /// 司令官---主题对象以及发布命令

    /// </summary>

    public class Commander : ISubject

    {

        #region ISubject 成员

        private List<Observer> _observers;

        public List<Observer> Observers

        {

            get

            {

                return _observers;

            }

            set

            {

                _observers = value;

            }

        }



        public Command Command = new NoCommand();



        public Commander()

        {

            _observers = new List<Observer>();

        }



        public void RegisterObserver(Observer observer)

        {

            this.Observers.Add(observer);

        }



        public void RemoveObserver(Observer observer)

        {

            this.Observers.Remove(observer);

        }



        public void NotifyObservers()

        {

            foreach (Observer observer in this.Observers)

            {

                observer.Update(this.Command);

            }

        }



        #endregion



        public void SetCommand(Command command)

        {

            this.Command = command;

            NotifyObservers();

        }

    }



 /// <summary>

    /// 命令基类

    /// </summary>

    public abstract class Command

    {

        #region = Observer =



        private Observer _observer;



        public Observer Observer

        {

            get { return _observer; }

            set { _observer = value; }

        }



        #endregion

    

        public abstract void Execute();

    }



/// <summary>

    /// 攻击命令

    /// </summary>

    class AttackCommand : Command

    {

        



        #region Command 成员



        public override void Execute()

        {

            Console.WriteLine(string.Format("{0}:{1}", this.Observer.Name, this.Observer.AttackSlogan));

        }



        #endregion



    }



/// <summary>

    /// 撤退命令

    /// </summary>

    class RetreatCommand : Command

    {

        

        #region Command 成员



        public override void Execute()

        {

            Console.WriteLine(string.Format("{0}:{1}", this.Observer.Name, this.Observer.RetreatSlogan));

        }



        #endregion

    }



/// <summary>

    /// 空命令

    /// </summary>

    class NoCommand : Command

    {

        

        #region Command 成员



        public override void Execute()

        {



        }



        #endregion

    }





测试一下:
//实例化司令官和三个小队

            Commander commander = new Commander();

            AxeTeam axe = new AxeTeam();

            BowAndArrowTeam baa = new BowAndArrowTeam();

            KnifeTeam knife = new KnifeTeam();

            AttackCommand attackCommand = new AttackCommand();

            RetreatCommand retreatCommand = new RetreatCommand();



            //注册观察者

            commander.RegisterObserver(axe);

            commander.RegisterObserver(baa);

            commander.RegisterObserver(knife);

            //司令官下命令

            commander.SetCommand(attackCommand);

            commander.SetCommand(retreatCommand);

            //匕首小队怕死,从军队中删除

            Console.WriteLine("匕首小队怕死,从军队中删除");

            commander.RemoveObserver(knife);

            //司令官再次下命令

            commander.SetCommand(attackCommand);

            commander.SetCommand(retreatCommand);
观察者模式和命令模式已经结到一起,输出结果:
斧头小队:用斧头攻击,势死如归!
弓箭手小队:弓箭手掩护,退后十步,射箭!
匕首小队:匕首攻击,打不过就跑!
斧头小队:坚守阵地,死也不放弃!
弓箭手小队:边撤退,边掩护斧头小队!
匕首小队:快撤啊,我军大势已去!
匕首小队怕死,从军队中删除
斧头小队:用斧头攻击,势死如归!
弓箭手小队:弓箭手掩护,退后十步,射箭!
斧头小队:坚守阵地,死也不放弃!
弓箭手小队:边撤退,边掩护斧头小队! ------------------------- 至此,全部介结完毕,有错误之处还请大家指出。
### Java 命令模式 实现与应用 #### 1. 命令模式简介 命令模式Command Pattern)是一种行为型设计模式,其核心思想是将请求封装成对象。通过这种方式,可以实现客户端与接收者的解耦[^2]。 #### 2. 主要角色定义 - **Command 接口**:声明执行操作的方法。 - **ConcreteCommand 类**:具体的命令类,负责绑定 Receiver 和 Action。 - **Receiver 类**:实际执行命令的操作者。 - **Invoker 类**:调用 Command 的方法来执行命令。 - **Client 客户端**:创建 ConcreteCommand 对象并设置它的 Receiver。 #### 3. 示例代码实现 以下是一个完整的命令模式实验示例: ```java // Step 1: 定义 Command 接口 public interface Command { void execute(); } // Step 2: 创建 ConcreteCommand (打开灯的命令) public class LightOnCommand implements Command { private Light light; public LightOnCommand(Light light) { this.light = light; } @Override public void execute() { light.turnOn(); // 执行开灯动作 } } // Step 3: 创建另一个 ConcreteCommand (关闭灯的命令) public class LightOffCommand implements Command { private Light light; public LightOffCommand(Light light) { this.light = light; } @Override public void execute() { light.turnOff(); // 执行关灯动作 } } // Step 4: 创建 Receiver (Light 类) public class Light { public void turnOn() { System.out.println("The light is on."); } public void turnOff() { System.out.println("The light is off."); } } // Step 5: 创建 Invoker (RemoteControl 遥控器) public class RemoteControl { private Command command; public void setCommand(Command command) { this.command = command; } public void pressButton() { if (command != null) { command.execute(); // 调用命令的 execute 方法 } else { System.out.println("No command set!"); } } } // Step 6: 测试 Client public class TestCommandPattern { public static void main(String[] args) { Light livingRoomLight = new Light(); // 创建具体命令 Command lightOnCmd = new LightOnCommand(livingRoomLight); Command lightOffCmd = new LightOffCommand(livingRoomLight); // 创建遥控器实例 RemoteControl remote = new RemoteControl(); // 设置并测试开灯命令 remote.setCommand(lightOnCmd); remote.pressButton(); // 输出 "The light is on." // 设置并测试关灯命令 remote.setCommand(lightOffCmd); remote.pressButton(); // 输出 "The light is off." } } ``` #### 4. 代码解释 - `Command` 是接口,定义了一个抽象方法 `execute()`,所有的具体命令都需要实现该方法。 - `LightOnCommand` 和 `LightOffCommand` 是两个具体命令类,分别实现了开灯和关灯的功能。 - `Light` 是接收者类,包含了真正的业务逻辑(开灯和关灯的动作)。 - `RemoteControl` 是调用者类,它持有某个命令对象并通过调用 `execute()` 来触发相应的操作。 - 在 `TestCommandPattern` 中,展示了如何配置和使用这些组件。 #### 5. 应用场景 命令模式适用于以下情况: - 当需要对请求进行参数化、排队或记录日志时。 - 当需要支持撤销(Undo)、重做(Redo)等功能时。 - 当需要将复杂的操作分解为多个独立的小操作时。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值