设计模式(14)——命令模式

命令模式(Command Pattern)是一种数据驱动的设计模式,它属于行为型模式。请求以命令的形式包裹在对象中,并传给调用对象。调用对象寻找可以处理该命令的合适的对象,并把该命令传给相应的对象,该对象执行命令。

首先先定义一个Command接口

interface Command
{
    void Execute();
}

再定义几个Command的实现类

class Circle : Command
{
    public void Execute()
    {
        Console.WriteLine("执行圆");
    }
}
class Ring : Command
{
    public void Execute()
    {
        Console.WriteLine("执行圆环");
    }
}

定义一个封装类

class Invoke
{
    private List<Command> commandList;

    public Invoke()
    {
        commandList = new List<Command>();
    }
    public void AddCommand(Command command)
    {
        commandList.Add(command);
    }

    public void ExecuteCommand()
    {
        foreach(Command command in _commandList)
        {
            command.Execute();
        }
    }
}

调用

class Program
{
    static void Main(string[] args)
    {
        Command circle = new Circle();
        Command ring = new Ring();
        Invoke invoke = new Invoke();
        invoke.AddCommand(circle);
        invoke.AddCommand(ring);
        invoke.ExecuteCommand();
        Console.Read();
    }
}

结果

执行圆
执行圆环

类图

在这里插入图片描述

增加Undo/Redo操作

首先修改Command接口,增加一个Undo方法

interface Command
{
    void Execute();
    void Undo();
}

增加Comand接口实现类的Undo方法

class Circle : Command
{
    public void Execute()
    {
        Console.WriteLine("执行圆");
    }

    public void Undo()
    {
        Console.WriteLine("撤销圆");
    }
}
class Ring : Command
{
    public void Execute()
    {
        Console.WriteLine("执行圆环");
    }
    public void Undo()
    {
        Console.WriteLine("撤销圆环");
    }
}

修改封装类

class Invoke
{
    private List<Command> undoList;
    private List<Command> redoList;
    // 可撤销的步数,-1是无限步
    private int undoCount = -1;

    public Invoke()
    {
        undoList = new List<Command>();
        redoList = new List<Command>();
    }

    public void ExecuteCommand(Command command)
    {
        command.Execute();
        undoList.Add(command);

        // 保留最近undoCount次操作,删除最早操作
        if (undoCount != -1 && undoList.Count > undoCount)
        {
            undoList.RemoveAt(0);
        }

        // 执行新操作后清空redoList,因为这些操作不能恢复了
        redoList.Clear();
    }
    public void Undo()
    {
        if (undoList.Count <= 0)
        {
            return;
        }

        Command cmd = undoList[undoList.Count - 1];
        cmd.Undo();

        undoList.Remove(cmd);
        redoList.Add(cmd);
    }
    public void Redo()
    {
        if (redoList.Count <= 0)
        {
            return;
        }

        Command cmd = redoList[redoList.Count - 1];
        cmd.Execute();

        redoList.Remove(cmd);
        undoList.Add(cmd);

    }
}

修改调用

class Program
{
    static void Main(string[] args)
    {
        Command circle = new Circle();
        Command ring = new Ring();
        Invoke invoke = new Invoke();
        invoke.ExecuteCommand(circle);
        invoke.ExecuteCommand(ring);
        invoke.Undo();
        invoke.Redo();
        
		//无效操作
        invoke.Redo();
        
        //撤销两次
        invoke.Undo();  
        invoke.Undo();
        
        //恢复两次
        invoke.Redo();
        invoke.Redo();
        Console.Read();
    }
}

结果

执行圆
执行圆环
撤销圆环
执行圆环
撤销圆环
撤销圆
执行圆
执行圆环

类图

在这里插入图片描述

优点与缺点

命令模式的优点:

  • 命令模式使得新的命令很容易被加入到系统里。
  • 可以设计一个命令队列来实现对请求的Undo和Redo操作。
  • 可以较容易地将命令写入日志。
  • 可以把命令对象聚合在一起,合成为合成命令。合成命令式合成模式的应用。

命令模式的缺点:

  • 使用命令模式可能会导致系统有过多的具体命令类。这会使得命令模式在这样的系统里变得不实际。

本文主要借鉴了《Gof设计模式》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值