随笔-42  评论-128  文章-0  trackbacks-4
VS 2008

    应应用程序中,常常会有这样一些有状态的对象,它们可能有很多种状态,在不同状态下,对象表现出的行为截然不同。在一般情况下,我们可能会写一些状态切换的if .. else ..语句块,往往造成代码丑陋,维护困难。
    这时候,可以考虑使用状态模式。

1. 模式UML图




2. 应用

    现在程序中需要频繁造作一类对象,我们称之为案件(Task),一个案件的生命周期是一个流程,从受理、派遣、处理、到最终完成,经历四种状态(其实还有更多,这里为了示例,我把它简化了)。因此很容易想到使用状态模式。
    静态类图:



    现在来看代码,Very simple

Task.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPattern.State.BLL {
    
public class Task {

        
/// <summary>
        
/// 案件唯一编号
        
/// </summary>

        public string TaskId getset; }

        
/// <summary>
        
/// 状态
        
/// </summary>

        public ITaskState State {get;set;}

        
public Task(string taskId, ITaskState state) {
            
this.TaskId = taskId;
            
this.State = state;
        }


        
public void Execute() {
            
this.State.Execute(this);
        }

    }

}


ITaskState.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPattern.State.BLL {
    
public interface ITaskState {

        
void Execute(Task task);
    }

}


AcceptingState.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPattern.State.BLL {
    
public class AcceptingState : ITaskState {

        
ITaskState Members
    }

}


DispatchingState.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPattern.State.BLL {
    
public class DispatchingState : ITaskState {
        
ITaskState Members
    }

}


SolvingState.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPattern.State.BLL {
    
public class SolvingState : ITaskState {
        
ITaskState Members
    }

}


FinishedState.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPattern.State.BLL {
    
public class FinishedState : ITaskState {
        
ITaskState Members
    }

}


Client

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DesignPattern.State.BLL;

namespace DesignPattern.State {
    
class Program {
        
static void Main(string[] args) {

            Task t 
= new Task("0803A0007007"new AcceptingState());
            t.Execute();
            t.Execute();
            t.Execute();
            t.Execute();
        }

    }

}


Output

posted on 2008-03-20 20:05 Tristan(GuoZhijian) 阅读(2254) 评论(8)  编辑 收藏 所属分类: Design Pattern

评论:
#1楼  2008-03-21 09:02 | Kingthy      
这个模式好像看不出好处在哪..

假如用户不清楚里面有"task.State = new XXState();",下面这段代码让人看起来感到很迷惑:为什么要调用这么多次的Execute??
t.Execute();
t.Execute();
t.Execute();
t.Execute();

为什么不直接在"task.State = new XXState();"那里直接Execute呢?如:
public void Execute(Task task) {
Console.WriteLine("{0} solved", task.TaskId);
new FinishedState(Task);
}
这样某个ITaskState只对自己和它的下一级状态负责?这样不是更清晰吗?
  回复  引用  查看    
#2楼 [楼主] 2008-03-21 09:16 | Tristan(Guozhijian)      
@Kingthy

Client代码只是为了展示效果,可能没有实际意义,不多说了。

然后你说的第二个涉及两个问题

第一是关于什么时候传递context对象。
在new State构造函数里传递还是作为接口定义的方法参数传递都可以。
只不过用接口定义参数更严格,不是吗?

第二是否new XXState()哪里直接Execute,如果说是,那是不是不够灵活,如果我将来还要给各个XXState增加行为,那是不是改动很大?

:)




  回复  引用  查看    
#3楼  2008-03-21 10:13 | John Rambo      
IState实例相当于工作流中的节点。至于那四个连续的execute,是因为简便的缘故。。。很灵活,可以方便的扩展工作流
  回复  引用  查看    
#4楼 [楼主] 2008-03-21 11:00 | Tristan(Guozhijian)      
@John Rambo

that is it.
  回复  引用  查看    
#5楼  2008-03-21 11:19 | SMan [未注册用户]
不是很明白,比较郁闷,估计基础还不行
  回复  引用    
#6楼  2008-03-21 11:49 | 辨色龙      
如果能讲状态模式与策略模式的区别在哪里?就更好了
  回复  引用  查看    
#7楼 [楼主] 2008-03-21 12:57 | Tristan(Guozhijian)      
@辨色龙
Strategy:封装算法
State:封装基于状态的行为
  回复  引用  查看    
#8楼  2008-03-28 15:36 | wenwen5g [未注册用户]
楼主写得很认真啊。
很有收获哦。加油。
  回复  引用    

标题  
姓名  
主页
Email (博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      


相关链接: