webabcd - 专注于asp.net, html5, silverlight

ASP.NET
从现在开始 一切都不晚
posts - 287, comments - 7866, trackbacks - 594, articles - 0
  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理
[索引页]
[源码下载]


乐在其中设计模式(C#) - 状态模式(State Pattern)


作者:webabcd


介绍
允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它所属的类。


示例
有一个Message实体类,对它的操作有Insert()和Get()方法,持久化数据在SqlServer数据库中或Xml文件里。在对象内部可以根据用户的不同选择不同的数据持久化方案。



MessageModel
using System;
using System.Collections.Generic;
using System.Text;

namespace Pattern.State
{
    
/// <summary>
    
/// Message实体类
    
/// </summary>

    public class MessageModel
    
{
        
/// <summary>
        
/// 构造函数
        
/// </summary>
        
/// <param name="msg">Message内容</param>
        
/// <param name="pt">Message发布时间</param>

        public MessageModel(string msg, DateTime pt)
        
{
            
this._message = msg;
            
this._publishTime = pt;
        }


        
private string _message;
        
/// <summary>
        
/// Message内容
        
/// </summary>

        public string Message
        
{
            
get return _message; }
            
set { _message = value; }
        }


        
private DateTime _publishTime;
        
/// <summary>
        
/// Message发布时间
        
/// </summary>

        public DateTime PublishTime
        
{
            
get return _publishTime; }
            
set { _publishTime = value; }
        }

    }

}


AbstractMessageState
using System;
using System.Collections.Generic;
using System.Text;

namespace Pattern.State
{
    
/// <summary>
    
/// 状态模式抽象类
    
/// </summary>

    public abstract class AbstractMessageState
    
{
        
/// <summary>
        
/// Context类型
        
/// </summary>

        protected Message _message;

        
/// <summary>
        
/// Context类型属性
        
/// </summary>

        public Message Message
        
{
            
get return _message; }
            
set { _message = value; }
        }


        
/// <summary>
        
/// 改变状态
        
/// </summary>

        public abstract void StateChangeCheck();

        
/// <summary>
        
/// 获取Message
        
/// </summary>
        
/// <returns></returns>

        public abstract List<MessageModel> Get();

        
/// <summary>
        
/// 插入Message
        
/// </summary>
        
/// <param name="mm">Message实体对象</param>
        
/// <returns></returns>

        public abstract bool Insert(MessageModel mm);
    }

}


XmlMessage
using System;
using System.Collections.Generic;
using System.Text;

namespace Pattern.State
{
    
/// <summary>
    
/// Xml方式操作Message
    
/// </summary>

    public class XmlMessage : AbstractMessageState
    
{
        
/// <summary>
        
/// 构造函数
        
/// </summary>
        
/// <param name="message">Context类型参数</param>

        public XmlMessage(Message message)
        
{
            
this._message = message;
        }


        
/// <summary>
        
/// 改变状态
        
/// </summary>

        public override void StateChangeCheck()
        
{
            
// 如果UserId是admin则变换状态为SqlMessage
            if (this._message.UserId == "admin")
            
{
                
this._message.AbstractMessageState = new SqlMessage(this._message);
            }

        }


        
/// <summary>
        
/// 获取Message
        
/// </summary>
        
/// <returns></returns>

        public override List<MessageModel> Get()
        
{
            List
<MessageModel> l = new List<MessageModel>();
            l.Add(
new MessageModel("XML方式获取Message", DateTime.Now));

            
return l;
        }


        
/// <summary>
        
/// 插入Message
        
/// </summary>
        
/// <param name="mm">Message实体对象</param>
        
/// <returns></returns>

        public override bool Insert(MessageModel mm)
        
{
            
// 代码略
            return true;
        }

    }

}


SqlMessage
using System;
using System.Collections.Generic;
using System.Text;

namespace Pattern.State
{
    
/// <summary>
    
/// Sql方式操作Message
    
/// </summary>

    public class SqlMessage : AbstractMessageState
    
{
        
/// <summary>
        
/// 构造函数
        
/// </summary>
        
/// <param name="message">Context类型参数</param>

        public SqlMessage(Message message)
        
{
            
this._message = message;
        }


        
/// <summary>
        
/// 改变状态
        
/// </summary>

        public override void StateChangeCheck()
        
{

        }


        
/// <summary>
        
/// 获取Message
        
/// </summary>
        
/// <returns></returns>

        public override List<MessageModel> Get()
        
{
            List
<MessageModel> l = new List<MessageModel>();
            l.Add(
new MessageModel("SQL方式获取Message", DateTime.Now));

            
return l;
        }


        
/// <summary>
        
/// 插入Message
        
/// </summary>
        
/// <param name="mm">Message实体对象</param>
        
/// <returns></returns>

        public override bool Insert(MessageModel mm)
        
{
            
// 代码略
            return true;
        }

    }

}


Message
using System;
using System.Collections.Generic;
using System.Text;

namespace Pattern.State
{
    
/// <summary>
    
/// Context类
    
/// </summary>

    public class Message
    
{
        
/// <summary>
        
/// 类型为状态模式抽象类的私有变量
        
/// </summary>

        private AbstractMessageState _abstractMessageState;

        
/// <summary>
        
/// 类型为状态模式抽象类的属性
        
/// </summary>

        public AbstractMessageState AbstractMessageState
        
{
            
get return _abstractMessageState; }
            
set { _abstractMessageState = value; }
        }
       

        
/// <summary>
        
/// UserId私有变量
        
/// </summary>

        private string _userId;

        
/// <summary>
        
/// UserId
        
/// </summary>

        public string UserId
        
{
            
get return _userId; }
            
set { _userId = value; }
        }


        
/// <summary>
        
/// 构造函数
        
/// </summary>
        
/// <param name="userId">UserId</param>

        public Message(string userId)
        
{
            
this._userId = userId;

            _abstractMessageState 
= new XmlMessage(this);
        }


        
/// <summary>
        
/// 获取Message
        
/// </summary>
        
/// <returns></returns>

        public List<MessageModel> Get()
        
{
            
// 修改状态
            _abstractMessageState.StateChangeCheck();

            
return _abstractMessageState.Get();
        }


        
/// <summary>
        
/// 插入Message
        
/// </summary>
        
/// <param name="mm">Message实体对象</param>
        
/// <returns></returns>

        public bool Insert(MessageModel mm)
        
{
            
// 修改状态
            _abstractMessageState.StateChangeCheck();

            
return _abstractMessageState.Insert(mm);
        }

    }

}



client
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

using Pattern.State;

public partial class State : System.Web.UI.Page
{
    
protected void Page_Load(object sender, EventArgs e)
    
{
        Message m 
= new Message("admin");
        Response.Write(m.Insert(
new MessageModel("插入", DateTime.Now)));
        Response.Write(
"<br />");
        Response.Write(m.Get()[
0].Message + " " + m.Get()[0].PublishTime.ToString());
        Response.Write(
"<br />");

        m 
= new Message("user");
        Response.Write(m.Insert(
new MessageModel("插入", DateTime.Now)));
        Response.Write(
"<br />");
        Response.Write(m.Get()[
0].Message + " " + m.Get()[0].PublishTime.ToString());
        Response.Write(
"<br />");
    }

}


运行结果
True
SQL方式获取Message 2007-3-6 22:58:17
True
XML方式获取Message 2007-3-6 22:58:17


参考
http://www.dofactory.com/Patterns/PatternState.aspx


OK
[源码下载]

Feedback

#1楼  回复 引用   

2007-03-07 09:40 by ivw[未注册用户]
支持。。。

#2楼[楼主]  回复 引用 查看   

2007-03-07 13:59 by webabcd      
@ivw
:)
我打算把所有设计模式都再过一遍

#3楼  回复 引用 查看   

2007-03-07 22:39 by 张振      
好文,期待博主把所有的模式都写一遍

#4楼[楼主]  回复 引用 查看   

2007-03-08 08:19 by webabcd      
@张振
嗯,计划是这样的

#5楼  回复 引用   

2007-03-08 10:00 by ivw[未注册用户]
期待。。。

#6楼[楼主]  回复 引用 查看   

2007-03-08 13:07 by webabcd      
@ivw
:)

#7楼  回复 引用   

2007-11-25 20:52 by Evanz[未注册用户]
StateChangeCheck方法在XmlMessage和SqlMessage两个state类中实现好象有些不妥吧,如果有多个状态并且初始状态由外部传入参数决定的话,每个state中的StateChangeCheck方法又都是if...else...了,丝毫没有起到state模式应起的作用

#8楼[楼主]  回复 引用 查看   

2007-11-26 08:21 by webabcd      
@Evanz
我觉得状态模式解决的不是“初始状态由外部传入参数决定”
它的作用是在对象内部改变“状态”
有的时候if...else...是避免不了的

#9楼  回复 引用 查看   

2007-12-15 13:26 by qingfengtanying      
是呀 if else 不是什么时候都要与其它解耦的 设计模式虽然给我们带来很多解决问题的方法,但如果滥用设计模式也带给我们许多不必要的麻烦。所以思想才是设计的灵魂!!!!!

#10楼[楼主]  回复 引用 查看   

2007-12-17 00:35 by webabcd      
@qingfengtanying
:)
同意

#11楼  回复 引用   

2008-04-03 09:22 by 士大夫似的[未注册用户]
public override void StateChangeCheck()
{
// 如果UserId是admin则变换状态为SqlMessage
if (this._message.UserId == "admin")
{
this._message.AbstractMessageState = new SqlMessage(this._message);
}
}
觉得你的不对。本来就是为了避免if else 等情况,你的例子中还不如用工厂模式呢。

#12楼[楼主]  回复 引用 查看   

2008-04-03 11:42 by webabcd      
@士大夫似的
我是想通过实例的方式来说明一下,并不是说这样的需求就要用这样的模式

谁说的状态模式就是为了避免if else?
它的作用是允许一个对象在其内部状态改变时改变它的行为。

#13楼  回复 引用   

2008-04-11 21:29 by ve[未注册用户]
--引用--------------------------------------------------
Evanz: StateChangeCheck方法在XmlMessage和SqlMessage两个state类中实现好象有些不妥吧,如果有多个状态并且初始状态由外部传入参数决定的话,每个state中的StateChangeCheck方法又都是if...else...了,丝毫没有起到state模式应起的作用
--------------------------------------------------------
--引用--------------------------------------------------
士大夫似的: public override void StateChangeCheck()
{
// 如果UserId是admin则变换状态为SqlMessage
if (this._message.UserId == &quot;admin&quot;)
{
this._message.AbstractMessageState = new SqlMessage(this._message);
}
}
觉得你的不对。本来就是为了避免if else 等情况,你的例子中还不如用工厂模式呢。
--------------------------------------------------------
同意

#14楼[楼主]  回复 引用 查看   

2008-04-14 08:06 by webabcd      
@ve
:)
我写这些设计模式的用意是从代码的角度介绍如何使用设计模式

另外,我的观点是State Pattern并不是为了避免if...else...的出现
它的作用就是一句话:“允许一个对象在其内部状态改变时改变它的行为”

#15楼  回复 引用   

2008-11-26 10:35 by staticage[未注册用户]
同意 士大夫似的

楼主说的是没错
但是设计模式还有一个作用就是增强代码可读性

#16楼[楼主]  回复 引用 查看   

2008-11-26 12:30 by webabcd      
@staticage
:)
我觉得设计模式就是为了可扩展性,代码复用
为了oo的几个原则

至于可读性的话,我想过程化的开发的可读性更强
发表评论

昵称: [登录] [注册]

主页:

邮箱:(仅博主可见)

评论内容:

  登录  注册

[使用Ctrl+Enter键快速提交评论]

0 666128 sUy/dUbQifA=