状态模式-C#

yangchen0469

yangchen0469

2016-02-19 12:27

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

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

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

先对此场景做分析如下:

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

   任务的状态可以分为: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();
        }

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

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

        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);
        }

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

        /// 通知相关人员

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

            return work.deployTestManchine(this.taskIdInDataTable);
        }

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

    }

到此我们的任务类已经定义完成,其中有一个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开始运行:

Task  task = new Task (new WaitingTaskState);

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

展开更多 50%)
分享

猜你喜欢

状态模式-C#

编程语言 网络编程
状态模式-C#

用设计模式固化C#程序

编程语言 网络编程
用设计模式固化C#程序

s8lol主宰符文怎么配

英雄联盟 网络游戏
s8lol主宰符文怎么配

Singleton设计模式的C#实现

编程语言 网络编程
Singleton设计模式的C#实现

C#设计模式编程之抽象工厂模式新解

编程语言 网络编程
C#设计模式编程之抽象工厂模式新解

lol偷钱流符文搭配推荐

英雄联盟 网络游戏
lol偷钱流符文搭配推荐

利用C#实现标准的 Dispose模式

编程语言 网络编程
利用C#实现标准的 Dispose模式

Visual C#实现MVC模式简要方法

编程语言 网络编程
Visual C#实现MVC模式简要方法

lolAD刺客新符文搭配推荐

英雄联盟
lolAD刺客新符文搭配推荐

SQLServer数据对象结构的动态建立与访问

SQLServer数据对象结构的动态建立与访问

AJAX乱码解决新方法

AJAX乱码解决新方法
下拉加载更多内容 ↓