`
foo
  • 浏览: 27115 次
  • 来自: 北京
最近访客 更多访客>>
文章分类
社区版块
存档分类
最新评论

设计模式系列-命令模式

阅读更多

新的一年的春天到啦,又是一轮跳槽离职的高峰期,面对新的一年的开始大家都希望各个方面都在更上一层楼,难免会出现跳槽、离职创业等等现象,最近项目组有人离职啦,当然人走了活还是要有人干的嘛,如何合理的利用有限的人力资源把多余的活分配出去呢?这就是项目经理们考虑的事情啦!不过一般还是会出现一个开发人员同时兼有几个项目的现象啦~!OK,这个就是今天的场景,我们来用代码模拟一下吧!

        1.场景模拟

        首先我们考虑,当项目多,人手不够时,我们需要一个人去同时兼有好几个项目的工作,可能有开发也可能有运维!

        那么第一步我们先设计一个项目类,分别代表需要参与的项目,代码如下:

    /// <summary>
    
/// Web项目类
    
/// </summary>
    public class WebProject
    {
        /// <summary>
        
/// 项目名称
        
/// </summary>
        public string ProjectName { getset; }
    }

         接下来第二步,我们设计一个开发者类表示具体的开发人员,并且开发人员具有开发项目和运维项目的操作,代码如下:

    /// <summary>
    
/// 开发者
    
/// </summary>
    public class Developer
    {
        /// <summary>
        
/// 开发项目
        
/// </summary>
        
/// <param name="project">项目</param>
        public void Coding(WebProject project)
        {
            Console.WriteLine("开发{0}项目",project.ProjectName);
        }

        /// <summary>
        
/// 运维项目
        
/// </summary>
        
/// <param name="project">项目</param>
        public void UpdateRoutine(WebProject project)
        {
            Console.WriteLine("维护{0}项目", project.ProjectName);
        }
    }

        主函数调用方法如下:

    static void Main(string[] args)
    {
            //表示一个具体的项目名字叫:项目A
            WebProject wpA = new WebProject() { ProjectName = "项目A" };
            //表示一个具体的项目名字叫:项目B
            WebProject wpB = new WebProject() { ProjectName = "项目B" };

            //实例化一个开发者,程序员
            Developer dp = new Developer();

            //命令他开发项目A
            dp.Coding(wpA);
            //命令他开发项目B
            dp.UpdateRoutine(wpB);
    }

        这么简单的程序运行结果我就不贴出来啦,我们来看看上边的代码,我们把主函数的调用当做客户,我们发现如果客户直接和开发者形成这种紧耦合的状态是非常不好的,比如说,客户会提出很多业务上的要求,而开发者并不能很准确的估算出开发成本与时间,所以我们需要一个项目经理来与客户沟通,并且将客户提出的不合理需求过滤掉,在给开发人员发出一个命令将项目交给开发人员!也就是说需要将“命令发起者”与“命令实现者”分离!

        2.命令模式

         那么我们来看看实现“命令发起者”与“命令实现者”分离的设计模式,命令模式:

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

         命令模式结构图如下:

      

       ①接口ICommand:用来声明抽象一个命令操作的接口。

       ②ConcreteCommand:具体的命令实现,用来表示命令的类型例如上边场景中的开发项目和维护项目可分别实现为:开发项目命令,维护项目命令等。

       ③Receiver:具体命令的实现者,也就是说命令的执行者,相对于上边场景中的开发者。

       ④Invoker:命令的指挥者,用来设置命令,并且通知执行命令,相对于上边场景中的项目经理。

       了解完命令模式的概念后,我们用命令模式来实现上边的场景:

        首先是命令接口ICommand的实现,代码如下:

    public interface ICommand
    {
        void Excute(WebProject project);
    }

        接下来就是我们接受命令并且执行的实现者啦,也就是我们场景中的开发者,代码如下:

    /// <summary>
    
/// 开发者
    
/// </summary>
    public class Developer
    {
        /// <summary>
        
/// 开发项目
        
/// </summary>
        
/// <param name="project">项目</param>
        public void Coding(WebProject project)
        {
            Console.WriteLine("开发{0}项目", project.ProjectName);
        }

        /// <summary>
        
/// 运维项目
        
/// </summary>
        
/// <param name="project">项目</param>
        public void UpdateRoutine(WebProject project)
        {
            Console.WriteLine("维护{0}项目", project.ProjectName);
        }
    }

       现在有了命令的实现者,就应该有具体的命令啦,上边那场景中的命令分别有,开发命令与维护命令,具体代码如下:

  /// <summary>
    
/// 开发项目命令
    
/// </summary>
    public class CodingCommand : ICommand
    {
        Developer dp { getset; }
        public WebProject project { getset; }//所对应的项目

        public void Excute()
        {
            dp.Coding(project);
        }
    }

    /// <summary>
    
/// 维护项目命令
    
/// </summary>
    public class UpdateRoutineCommand : ICommand
    {
        Developer dp { getset; }
        public WebProject project { getset; }//所对应的项目

        public void Excute()
        {
            dp.UpdateRoutine(project);
        }
    }

       命令与实现者都就绪了,指挥调度者就该出现了,也就是项目经理,项目经理用来负责设置命令调度命令执行,代码如下:

    /// <summary>
    
/// 项目经理类
    
/// </summary>
    public class ProjectManager
    {
        List<ICommand> cmdList = new List<ICommand>();

        /// <summary>
        
/// 设置命令
        
/// </summary>
        
/// <param name="cmd"></param>
        public void SetCommand(ICommand cmd)
        {
            cmdList.Add(cmd);
        }

        /// <summary>
        
/// 发起命令
        
/// </summary>
        public void ExcuteCommand()
        {
            cmdList.ForEach(p => p.Excute());
        }
    }

       代码写好后,我们来模拟一下调用吧,现在项目经理需要分配给开发者两个任务,一个是开发项目A,另一个是维护项目B!主函数调用如下:

            //表示一个具体的项目名字叫:项目A
            WebProject wpA = new WebProject() { ProjectName = "项目A" };
            //表示一个具体的项目名字叫:项目B
            WebProject wpB = new WebProject() { ProjectName = "项目B" };
            //开发者
            Developer developer= new Developer();

            //开发者所需要接收的命令
            ICommand codeCmd = new CodingCommand() { project = wpA, dp = developer };
            ICommand UpdateCmd = new UpdateRoutineCommand() { project = wpB, dp = developer };

            //项目经理
            ProjectManager pm = new ProjectManager();
            //设置命令
            pm.SetCommand(codeCmd);
            pm.SetCommand(UpdateCmd);
            //发起命令让开发者去完成
            pm.ExcuteCommand();
}

       那么一个简单的命令模式就完成了。

      3.更加灵活的分配任务

       接下来我们在增加一些要求:

       ①项目经理每次发起的命令都需要记录下来,年底好根据开发者的工作量评估奖金。

       ②项目经理可以撤销发起的命令,例如:撤销维护项目B的命令,让开发者专心做项目A的开发工作。

       回顾下命令模式的定义,上边两条需求就等同于定义中的“队请求排队或者记录请求日志,以及支持可撤销的操作

       那么我们给需求中加入一个方法用来撤销命令,因为项目经理类中已经有一个集合来记录命令的总数了,所以已经实现了请求记录的功能啦,我们只需加入撤销功能就好了。

       首先,给ICommand接口加入一个Cancel方法,用来表示撤销操作,因为命令撤销了需要通知实现者做一些撤销的工作,代码如下:

    public interface ICommand
    {
        void Excute();
        void Cancel();
    }

      接下来既然有取消了,那么开发者受到取消命令后要执行一些关于取消的代码,所以开发者类加入一个方法StopCoding,表示停止项目的工作,代码如下:

  /// <summary>
    
/// 开发者
    
/// </summary>
    public class Developer
    {
        /// <summary>
        
/// 开发项目
        
/// </summary>
        
/// <param name="project">项目</param>
        public void Coding(WebProject project)
        {
            Console.WriteLine("开发{0}项目", project.ProjectName);
        }

        /// <summary>
        
/// 运维项目
        
/// </summary>
        
/// <param name="project">项目</param>
        public void UpdateRoutine(WebProject project)
        {
            Console.WriteLine("维护{0}项目", project.ProjectName);
        }

        /// <summary>
        
/// 停止项目的工作
        
/// </summary>
        
/// <param name="project"></param>
        public void StopCoding(WebProject project)
        {
            Console.WriteLine("停止{0}项目",project.ProjectName);
        }
    }

      修改实际的命令类实现撤销命令的方法,并调用开发者类的StopCoding方法做撤销命令的工作,代码如下:

/// <summary>
    
/// 开发项目命令
    
/// </summary>
    public class CodingCommand : ICommand
    {
        public Developer dp { getset; }
        public WebProject project { getset; }//所对应的项目

        public void Excute()
        {
            dp.Coding(project);
        }

        /// <summary>
        
/// 撤销操作
        
/// </summary>
        public void Cancel()
        {
            dp.StopCoding(project);
        }
    }

    /// <summary>
    
/// 维护项目命令
    
/// </summary>
    public class UpdateRoutineCommand : ICommand
    {
        public Developer dp { getset; }
        public WebProject project { getset; }//所对应的项目

        public void Excute()
        {
            dp.UpdateRoutine(project);
        }

        /// <summary>
        
/// 撤销操作
        
/// </summary>
        public void Cancel()
        {
            dp.StopCoding(project);
        }
    }

       接下来就是命令的指挥者啦,项目经理首先设置一个撤销命令,并且将执撤销命令,在执行撤销命令的时候首先要将命令从集合中移除,因为该开发者已经不参与该撤销项目的工作了,所以不记录考核依据中,在调用命令中的撤销方法让开发者做具体的撤销工作。代码如下:

/// <summary>
    
/// 项目经理类
    
/// </summary>
    public class ProjectManager
    {
        List<ICommand> cmdList = new List<ICommand>();

        /// <summary>
        
/// 设置命令
        
/// </summary>
        
/// <param name="cmd"></param>
        public void SetCommand(ICommand cmd)
        {
            cmdList.Add(cmd);
        }

        /// <summary>
        
/// 发起命令
        
/// </summary>
        public void ExcuteCommand()
        {
            cmdList.ForEach(p => p.Excute());
        }

        /// <summary>
        
/// 返回记录行数
        
/// </summary>
        
/// <returns></returns>
        public int GetCommandCount()
        {
            return cmdList.Count;
        }

        /// <summary>
        
/// 撤销命令
        
/// </summary>
        
/// <param name="cmd"></param>
        public void CancelExectueCommand(ICommand cmd)
        {
            cmd.Cancel();
            cmdList.Remove(cmd);
        }
    }

     可见对功能的封装和“请求与实现分离”,可以让我们很容易的进行撤销与记录的工作,可以再命令执行前作一些必须要的操作。主函数调用如下:

        static void Main(string[] args)
        {
            //表示一个具体的项目名字叫:项目A
            WebProject wpA = new WebProject() { ProjectName = "项目A" };
            //表示一个具体的项目名字叫:项目B
            WebProject wpB = new WebProject() { ProjectName = "项目B" };
            //开发者
            Developer developer= new Developer();

            //开发者所需要接收的命令
            ICommand codeCmd = new CodingCommand() { project = wpA, dp = developer };
            ICommand UpdateCmd = new UpdateRoutineCommand() { project = wpB, dp = developer };

            //项目经理
            ProjectManager pm = new ProjectManager();
            //设置命令
            pm.SetCommand(codeCmd);
            pm.SetCommand(UpdateCmd);
            //发起命令让开发者去完成
            pm.ExcuteCommand();

            pm.CancelExectueCommand(UpdateCmd);//撤销UpdateCmd命令
         }

       命令模式总结:

       ①它能很容易的维护所有命令的集合。

       ②它可以很方便的实现撤销和恢复命令。

       ③可以很方便的将每个执行记录日志。

       ④最重要的就是将发起者与实现者分离。

分享到:
评论

相关推荐

    设计模式精解-GoF-23种设计模式解析--附C++源代码

    - 命令模式(Command):将请求封装为一个对象,以便使用不同的请求、队列请求、或者支持可撤销的操作。 - 解释器模式(Interpreter):给定一种语言,定义它的文法表示,并提供一个解释器来处理这种语言中的句子...

    设计模式精解-GoF 23种设计模式解析附C++实现源码

    ### 设计模式精解——GoF 23种设计模式解析及C++实现源码 #### 引言 设计模式是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。GoF(Gang of Four)所提出的23种设计模式,被认为是面向对象...

    C# 设计模式系列教程-命令模式

    命令模式是一种设计模式,主要目的是为了降低行为请求者与行为实现者之间的耦合度,使得系统更加灵活,便于扩展和维护。在C#中,我们可以利用接口和面向对象的特性来实现这一模式。 1. **概述** 命令模式的核心...

    设计模式-命令模式

    命令模式是一种行为设计模式,它将请求封装为一个对象,从而使你可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作。在iOS开发中,命令模式尤其适用于处理事件驱动的编程场景,因为...

    java设计模式---诙谐易懂版

    根据给定文件内容,以下是关于Java设计模式的知识点说明: 1. 策略模式(Strategy Pattern)是一种行为设计模式,允许在运行时选择算法的行为。策略模式的意图是定义一系列算法,将每个算法封装起来,并使它们可以...

    设计模式精解-GoF23种设计模式解析附C++实现源码

    - 命令模式(Command):将一个请求封装为一个对象,以便使用不同的请求、队列请求、或者支持可撤销的操作。 - 解释器模式(Interpreter):给定一种语言,定义它的文法表示,并提供一个解释器来处理这种语言中的...

    设计模式精解-GoF 23种设计模式解析附C++实现源码.pdf

    ### 设计模式精解——GoF 23种设计模式解析及C++实现源码 #### 0. 引言 设计模式是软件工程领域的一个重要概念,它提供了一种解决常见问题的方法论。GoF(Gang of Four)所提出的23种设计模式被视为面向对象设计的...

    Java设计模式----通俗易懂版

    这个资源"Java设计模式----通俗易懂版"显然是一个专门针对初学者或需要深入理解设计模式的开发者编写的指南。作者以形象生动的例子解释了23种经典的Java设计模式,使得复杂的概念变得更加易于理解。 首先,我们要...

    设计模式精解-GoF 23种设计模式解析附C++实现源码 完整版

    《设计模式精解-GoF 23种设计模式解析附C++实现源码 完整版》是一份深入探讨软件工程中经典设计模式的重要资料,涵盖了面向对象编程中的核心设计原则和实践。这份资源主要关注GoF(Gang of Four,即《设计模式:可...

    设计模式精解-GoF 23种设计模式

    15. **命令模式**:将请求封装为一个对象,使得可以使用不同的请求、队列请求,或者支持可撤销的操作。 16. **解释器模式**:定义了一个表达式接口,让相关类实现这个接口来解释特定的语言。 17. **迭代器模式**:...

    设计模式-命令模式(讲解及其实现代码)

    命令模式是一种行为设计模式,它将请求封装为一个对象,从而使你可用不同的请求对客户进行参数化,对请求排队或记录请求日志...在需要处理一系列操作序列或支持撤销/重做的场景中,命令模式是一个非常实用的设计模式。

    设计模式PPT---25种设计模式详解

    这份名为“设计模式PPT——25种设计模式详解”的资料,显然是一个深入探讨设计模式的教程,它通过PDF格式对25种主要的设计模式进行了详尽的阐述。 首先,我们要理解设计模式的基本概念。设计模式不是代码,而是一种...

    设计模式学习笔记-命令模式

    命令模式是一种行为设计模式,它的主要目的是将请求封装为对象,以便于参数化不同请求、队列请求、记录请求日志以及支持撤销和重做操作。在软件开发中,它帮助解耦了请求发起者(调用者)和请求执行者(接收者),...

    23种 设计模式---面向对象的基本原则

    - 命令模式(Command):将一个请求封装为一个对象,以便使用不同的请求、队列或者日志请求,支持可撤销的操作。 - 解释器模式(Interpreter):给定一种语言,定义它的文法表示,并提供一个解释器来处理该语言中...

    23种设计模式代码-c#

    - 命令模式:将请求封装为一个对象,以便使用不同的请求、队列请求或参数化请求。 - 解释器模式:实现一个简单的语言解释器。 - 迭代器模式:提供一种方法顺序访问聚合对象的元素,而又不暴露其底层表示。 - ...

Global site tag (gtag.js) - Google Analytics