状态模式-C#

2016-02-19 12:27 33 1 收藏

图老师设计创意栏目是一个分享最好最实用的教程的社区,我们拥有最用心的各种教程,今天就给大家分享状态模式-C#的教程,热爱PS的朋友们快点看过来吧!

【 tulaoshi.com - 编程语言 】

状态模式主要解决当控制一个对象状态的转换的条件表达过于复杂的情况,使得状态的转换不依赖于整体的操作。本文将通过一个具体的例子说明状态模式的应用。假设下面一个场景:

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/bianchengyuyan/)

     一个新任务提交后,先是收集数据,数据收集完成后等等分配一台机器,分配到机器后就可以将此任务部署至此机器后就可以通知相关模块开始工作。

先对此场景做分析如下:

   一个任务共分四个步骤:一收集数据,二分配机器,三部署到测试机,四通知相关对象。

   任务的状态可以分为:new, waiting, Ready, Running分别对应新任务提交,等待分配机器,准备部署,和部署完成于上面的步骤一一对应。

定义一个任务类:

 /*abstract*/ class Task : IGatherData, IAllotMachine, IDeployTestManchine, INotifyUser   // 这里是分别为以上四个步骤定义的接口
    {

        // 任务在数据库里对应的ID
        private string taskIdInDataTable;
        public string TaskIdInDataTable
        {
            get
            {
                return taskIdInDataTable;
            }
            set
            {
                taskIdInDataTable = value;
            }
        }

        // 任务的状态

        private TaskState _TaskState;
        public TaskState TaskState
        {
            get
            {
                return _TaskState;
            }

            set
            {
                _TaskState = value;
                Log.Info("当前状态:" + _TaskState.GetType().Name);
            }
        }

        public Task()
        {
            this._TaskState = new NewTaskState();
        }

       // 可以指定一个任务的当前状态

        public UpDateTask(TaskState taskTask)
        {
            this._TaskState = taskTask;
        }

        /// summary 改变一个任务的状态至当前任务的下一个状态
        /// /summary
        public void ChangeState()
        {
            System.Threading.Thread.Sleep(500);
            this._TaskState.ChangeState(this);
        }

        /// 以下是实现接口中的方法       
        /// 合并数据
        public virtual bool gatherData()
        {

            return true;
        }

        /// 分配机器
        /// 分配机器放在基类里面做,因为这个动作对每个任务来说基本都是一样的
        public virtual bool allotMachine()
        {
            DoWork work = new DoWork();

            return work.allotMachine(this.taskIdInDataTable);
        }


        /// 部署至测试机
        /// 部署至测试机放在基类里面做,因为这个动作对每个任务来说基本都是一样的
        public virtual bool deployTestManchine()
        {
            DoWork work = new DoWork();

            return work.deployTestManchine(this.taskIdInDataTable);
        }

        /// 通知相关人员

        /// 通知相关人员放在基类里面做,因为这个动作对每个任务来说基本都是一样的
        public virtual bool deployTestManchine()
        {
            DoWork work = new DoWork();

            return work.deployTestManchine(this.taskIdInDataTable);
        }

    }

到此我们的任务类已经定义完成,其中有一个ChangeState的方法,此方法负责调用状态类的改变状态的方法。

接下面就写Status类:

先是定义一个超类,此类只有一个方法就是ChangeState, 此方法负责控制任务状态的转换。

abstract class TaskState
    {
        /// summary状态改变过程
        /// /summary状态的改变由统一的接口进行从一个状态到下一下状态的改变,
        ///           使用时不用关心内部的状态是怎么改变的,只需统一调用此方法即可。
        /// param name="task"/param
        public abstract void ChangeState(UpDateTask task);
    }

下面定义具体的状态类:

// 新任务状态
    class NewTaskState: TaskState
    {
        public override void ChangeState(UpDateTask task)
        {
            // 检查当前状态
            if (this == task.TaskState)
            {               
                if (task.gatherData())
                {
                    task.TaskState = new WaitingTaskState(task);
                }
                else // 如果合并数据任务失败,将任务打到已清除状态
                {
                    task.TaskState = new DeletedState(task);
                }
            }           
        }

        public NewTaskState()
        {

        }

        public NewTaskState(UpDateTask task)
        {
            DoWork.setTaskState(task.TaskIdInDataTable,  enumTaskState.NewTask);
        }
    }

    // 等待任务状态
    class WaitingTaskState : TaskState
    {
        public override void ChangeState(UpDateTask task)
        {
            if (this == task.TaskState)
            {
                if (task.allotMachine())
                {
                    task.TaskState = new ReadyTaskState(task);
                }
                else
                {
                    task.TaskState = new WaitingTaskState(task);                  
                }
            }           
        }

        public WaitingTaskState()
        {
          
        }

        public WaitingTaskState(UpDateTask task)
        {
            DoWork.setTaskState(task.TaskIdInDataTable, enumTaskState.Waiting);          
        }

    }

    // 准备任务状态
    class ReadyTaskState : TaskState
    {
        public override void ChangeState(UpDateTask task)
        {
            if (this == task.TaskState)
            {
                if (task.deployTestManchine())
                {
                    task.TaskState = new RunningState(task);
                }
                else
                {
                    // 部署失败则重新分配新的测试机器
                    task.TaskState = new WaitingTaskState(task);
                }
            }           
        }


        public ReadyTaskState()
        {
           
        }

        public ReadyTaskState(UpDateTask task)
        {
            DoWork.setTaskState(task.TaskIdInDataTable, enumTaskState.Ready);           
        }

      
    }

    // 运行任务状态
    class RunningState : TaskState
    {
        public override void ChangeState(UpDateTask task)
        {         
            // send e-mail      
          
        }    
  
       
        public RunningState()
        {
           
        }

        public RunningState(UpDateTask task)
        {
            DoWork.setTaskState(task.TaskIdInDataTable, enumTaskState.Running);
        }
    }

 // 下来看客户端调用

Task  task = new Task ();

task.TaskIdInDataTable = 1111;  // 为此任务指定一个ID

下来就最重要的,做了这么多事就是为了下面的调用:

task.ChangeState();

task.ChangeState();

task.ChangeState();

task.ChangeState();

这样此任务就完成了,客户端根本不用关心任务的状态是怎么转换的,因为每一个状态的转换都是由当前的状态决定自己的下一个状态是什么,即使要修改状态的流程也只需要修改状态类就可以,也不用关心具体的操作。这样做很方便的将状态转换、任务的具体步骤、与客户端的调用分开,之间不受影响。

也可以指定一个任务的当前状态,从此状态开始,比如可以指定此任务从Wating开始,此任务就会从Waiting对应的allotMachine开始运行:

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/bianchengyuyan/)

Task  task = new Task (new WaitingTaskState);

到此状态模式的应该已全部写完。

来源:http://www.tulaoshi.com/n/20160219/1600927.html

延伸阅读
本系列文章将向大家介绍一下 C#的设计模式 ,此为第十三篇文章,相信对大家会有所帮助的。废话不多说,继续来看。 意图 动态地给一个对象添加一些额外的职责。就增加功能来说,Decorator模式相比生成子类更为灵活。 场景 在设计网络游戏的武器系统时,开始并没有考虑到武器的强化和磨损。之后,策划人员说希望给游...
应该说,从 C/C++ 发展到 C#,进而到 Microsoft .NET Framework,对于习惯使用 C/C++ 的程序员来说是一次小小的打击。换句话说,C# 编程将带来翻天覆地的变化,不仅要完成范例转换,还要完成程序模型的重建以及其他各种令人难以捉摸的词组转变。但是,随着新一年的到来,不正是学习新编程语言的好时机吗? 我现在实在是抽不出时间教您如何使...
在过去的二十年里,C和C++已经成为在商业软件的开发领域中使用最广泛的语言。它们为程序员提供了十分灵活的操作,不过同时也牺牲了一定的效率。与诸如Microsoft? Visual Basic? 等语言相比,同等级别的C/C++应用程序往往需要更长时间来开发。由于C/C++语言的复杂性,许多程序员都试图寻找一种新的语言,希望能在功能与效率之间找到一个更...
   1 绪论 c# 是一种简练,时髦(?),面向对象(object oriented),类型可靠(type-safe)的 编程语言。它(发音:C sharp)是从c/c++发展而来的(?俺觉得更象是java),和c/c++ 是一个语系。所以,很容易被c/c++的程序员接受。c#的目标是结合Visual Basic的高产和 C++质朴的力量。 c#将会是vs7的一分子。vs7还支持vb,vc和...
About program language such as C++, C#, Java and Delphi, how to choose a good one for a freshman ? This view has pointed by many people here and different person have different ideas. In my opnion, , C# is the first choose for anyone. Why? Because it's different from any other language. C# comes from C++ and Java i...

经验教程

353

收藏

69
微博分享 QQ分享 QQ空间 手机页面 收藏网站 回到头部