Net设计模式实例之命令模式(Command Pattern)

简介: 一、命令模式简介(Brief Introduction) 命令模式(Command Pattern)将请求封装为一个对象,从而使你用不同的请求对客户进行参数化,对请求排队或纪录请求日志,以及支持可撤销的操作。

一、命令模式简介(Brief Introduction

命令模式(Command Pattern)将请求封装为一个对象,从而使你用不同的请求对客户进行参数化,对请求排队或纪录请求日志,以及支持可撤销的操作。

Encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations

二、解决的问题(What To Solve

       当需要有撤销或者恢复操作时,可以考虑使用命令模式。

三、命令模式分析(Analysis

1、命令模式结构

Command抽象类:声明一个接口,用于执行操作,declares an interface for executing an operation

ConcreteCommand实现类:将一个接收者对象绑定到一个动作。调用接收者相应的操作,以实现Execute

defines a binding between a Receiver object and an action

implements Execute by invoking the corresponding operation(s) on Receiver

Receiver:知道如何执行一个请求相关的操作。knows how to perform the operations associated with carrying out the request.

Invoker:要求命令执行一个请求。asks the command to carry out the request

2、源代码

1Command抽象类声明一个接口,用于执行操作

abstract class Command

{

    protected Receiver receiver;

 

    public Command(Receiver receiver)

    {

        this.receiver = receiver;

    }

    public abstract void Execute();

}

 

2ConcreteCommand具体实现类:将一个接收者对象绑定到一个动作

class ConcreteCommand : Command

{

    // Constructor

    public ConcreteCommand(Receiver receiver)

        :base(receiver)

    {

    }

    public override void Execute()

    {

        receiver.Action();

    }

}

 

3Receiver类:知道如何执行一个请求相关的操作

class Receiver

{

    public void Action()

    {

        Console.WriteLine("Called Receiver.Action()");

    }

}

 

4Invoker类:要求命令执行一个请求

class Invoker

{

    private Command _command;

    public void SetCommand(Command command)

    {

        this._command = command;

    }

    public void ExecuteCommand()

    {

        _command.Execute();

    }

}

 

4、客户端代码

static void Main(string[] args)

{

    // Create receiver, command, and invoker

    Receiver receiver = new Receiver();

    Command command = new ConcreteCommand(receiver);

    Invoker invoker = new Invoker();

 

    // Set and execute command

    invoker.SetCommand(command);

    invoker.ExecuteCommand();

 

    Console.ReadKey();

}

3、程序运行结果

四.案例分析(Example

1、场景

使用命令模式进行计算器计算,可以是加减乘除等运算,可以进行Undo操作和Rodo操作。如下图所示

 

Command抽象命令类:声明一个接口,用于执行操作。

CalculatorCommand具体实现类:将一个接收者对象绑定到一个动作。调用接收者相应的操作,以实现Execute

UnExecute方法:执行Undo操作。

Calculator -Operation方法:执行加减乘除操作。

User:要求命令Calculator执行一个计算请求。

Compute方法:加减乘除等计算操作

Undo方法:撤销操作。Redo方法:重复操作。

2、代码

1、抽象命令类Command及其计算器类CalculatorCommand

/// <summary>

/// The 'Command' abstract class

/// </summary>

abstract class Command

{

    public abstract void Execute();

    public abstract void UnExecute();

}

/// <summary>

/// The 'ConcreteCommand' class

/// </summary>

class CalculatorCommand : Command

{

    private char _operator;

    private int _operand;

    private Calculator _calculator;

    // Constructor

    public CalculatorCommand(Calculator calculator,char @operator, int operand)

    {

        this._calculator = calculator;

        this._operator = @operator;

        this._operand = operand;

    }

    // Gets operator

    public char Operator

    {

        set { _operator = value; }

    }

    // Get operand

    public int Operand

    {

        set { _operand = value; }

    }

    // Execute new command

    public override void Execute()

    {

        _calculator.Operation(_operator, _operand);

    }

    // Unexecute last command

    public override void UnExecute()

    {

        _calculator.Operation(Undo(_operator), _operand);

    }

    // Returns opposite operator for given operator

    private char Undo(char @operator)

    {

        switch (@operator)

        {

            case '+': return '-';

            case '-': return '+';

            case '*': return '/';

            case '/': return '*';

            default: throw new

             ArgumentException("@operator");

        }

    }

}

 

2、计算器类Calculator

/// <summary>

/// The 'Receiver' class

/// </summary>

class Calculator

{

    private int _curr = 0;

    public void Operation(char @operator, int operand)

    {

        switch (@operator)

        {

            case '+': _curr += operand; break;

            case '-': _curr -= operand; break;

            case '*': _curr *= operand; break;

            case '/': _curr /= operand; break;

        }

        Console.WriteLine(

          "Current value = {0,3} (following {1} {2})",

          _curr, @operator, operand);

    }

}

 

3、请求类User

/// <summary>

/// The 'Invoker' class

/// </summary>

class User

{

    // Initializers

    private Calculator _calculator = new Calculator();

    private List<Command> _commands = new List<Command>();

    private int _current = 0;

    public void Redo(int levels)

    {

        Console.WriteLine("\n---- Redo {0} levels ", levels);

        // Perform redo operations

        for (int i = 0; i < levels; i++)

        {

            if (_current < _commands.Count - 1)

            {

                Command command = _commands[_current++];

                command.Execute();

            }

        }

    }

    public void Undo(int levels)

    {

        Console.WriteLine("\n---- Undo {0} levels ", levels);

        // Perform undo operations

        for (int i = 0; i < levels; i++)

        {

            if (_current > 0)

            {

                Command command = _commands[--_current] as Command;

                command.UnExecute();

            }

        }

    }

    public void Compute(char @operator, int operand)

    {

        // Create command operation and execute it

        Command command = new CalculatorCommand(

          _calculator, @operator, operand);

        command.Execute();

        // Add command to undo list

        _commands.Add(command);

        _current++;

    }

 

4、客户端代码

static void Main(string[] args)

{

    // Create user and let her compute

    User user = new User();

    // User presses calculator buttons

    user.Compute('+', 100);

    user.Compute('-', 50);

    user.Compute('*', 10);

    user.Compute('/', 2);

    // Undo 4 commands

    user.Undo(4);

    // Redo 3 commands

    user.Redo(3);

    Console.ReadKey();

}

 

3、程序运行结果

五、总结(Summary

命令模式(Command Pattern)将请求封装为一个对象,从而使你用不同的请求对客户进行参数化,对请求排队或纪录请求日志,以及支持可撤销的操作。当需要有撤销或者恢复操作时,可以考虑使用命令模式。

 

版权

作者:灵动生活 郝宪玮

出处:http://www.cnblogs.com/ywqu

如果你认为此文章有用,请点击底端的【推荐】让其他人也了解此文章,

img_2c313bac282354945ea179a807d7e70d.jpg

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

 

相关文章
|
开发框架 .NET 数据库
.NETCore 获取数据库上下文[实例的方法和配置连接字符串
.NETCore 获取数据库上下文[实例的方法和配置连接字符串
787 1
|
开发框架 .NET API
Hangfire .NET任务调度框架实例
# 1、介绍 Hangfire是一个开源的.NET任务调度框架,提供了内置集成化的控制台(后台任务调度面板),可以直观明了的查看作业调度情况。 # 2、Nuget安装 ![请在此添加图片描述](https://developer-private-1258344699.cos.ap-guangzhou.myqcloud.com/column/article/5877188/20231031-119e3068.png?x-cos-security-token=baeOYKJ0BOuKXaDG6L8qKX7pdH823CLaaefd8181d9b33eccf4b2a2f35cd15dd7jLbyf
102 0
Hangfire .NET任务调度框架实例
|
调度
Quartz.NET 任务调度框架的demo实例
​ # 1、新建项目 简单实例,新建一个控制台程序 # 2、Nuget安装Quartz ![请在此添加图片描述](https://developer-private-1258344699.cos.ap-guangzhou.myqcloud.com/column/article/5877188/20231031-52d48c93.png?x-cos-security-token=baeOYKJ0BOuKXaDG6L8qKX7pdH823CLa740df95695ddd90763a204f7cd7172afjLbyfjQS2rqYm0waz5Rlsx3p2jhWg-yj9JZ3WKDq32bpX
70 0
|
XML 开发框架 安全
【浅谈ASP.NET】——Web服务应用实例
【浅谈ASP.NET】——Web服务应用实例
168 0
【浅谈ASP.NET】——Web服务应用实例
|
存储 SQL 数据库连接
浅谈ADO.NET中的对象——Connection、Command、DataReader、DataAdapter、DataSet、DataTable
可能是当初没有好好总结的缘故,学习.NET以来,对ADO.NET中的对象一直有些模糊,今天重新回顾了一下,通过查资料,总结,结合自己的观点整理一下ADO.NET中Connection、Command、DataReader、DataAdapter、
浅谈ADO.NET中的对象——Connection、Command、DataReader、DataAdapter、DataSet、DataTable
.Net Micro Framework研究—应用实例
在前几篇关于.Net Micro Framework的研究文章中,我对它的绘图功能实不敢恭维,不过微软的MF开发人员很聪明,对位图方面的功能实现的就比较完善,这样做起图形应用来就不至于捉襟见肘了。前段时间用.Net Compact Framework实现了一个奥运场馆查询
562 0
|
前端开发 .NET C#
ASP.NET Core MVC 设计模式 - ASP.NET Core 基础教程 - 简单教程,简单编程
原文:ASP.NET Core MVC 设计模式 - ASP.NET Core 基础教程 - 简单教程,简单编程   ASP.NET Core MVC 设计模式 上一章节中,我们提到 ASP.NET Core 支持 MVC 开发模式,不知道大家对 MVC 设计模式是否了解,算了,不管了,本章节我们就来讲讲 MVC 设计模式吧。
2382 0
|
前端开发 .NET Java
52ABP模板 ASP.Net Core 与 Angular的开源实例项目
阅读文本大概需要 5 分钟。 关注角落的白板报 开始之前 自从上一篇文章".NET:持续进化的统一开发平台"发布后,已经有三个月的时间没有写过文章了。
1745 0
|
Web App开发 存储 NoSQL
Asp.Net Core Web Api图片上传(一)集成MongoDB存储实例教程
Asp.Net Core Web Api图片上传及MongoDB存储实例教程(一) 图片或者文件上传相信大家在开发中应该都会用到吧,有的时候还要对图片生成缩略图。那么如何在Asp.Net Core Web Api实现图片上传存储以及生成缩略图呢?今天我就使用MongoDB作为图片存储,然后使用SixLabors作为图片处理,通过一个Asp.
1431 0