超级大笨狼:经验技巧分享-ASP.NET和Ajax应用一个超级实用的设计模式-享元模式(泛型实现,模式名字不重要,关键是有用!),该如何解决

超级大笨狼:经验技巧分享--ASP.NET和Ajax应用一个超级实用的设计模式---享元模式(泛型实现,模式名字不重要,关键是有用!)
在Web开发中,你是否困惑某些设计模式没什么用途或者不知所云?偶有心得,兴奋之余,不想独吞,特发出来大家分享.

问题起源:

1,Session["变量名称"]对于编程,使用起来不方便,如果Session里面需要存储的变量名称过多,敲字符比较麻烦,如果根据Session["userID"]去数据库里存取,损失性能.

2,对于站内即时短消息,聊天,下棋性质的的程序,需要知道私聊对方的一些属性,由于通信频繁,而有些数据又没有长期保存的必要,所以需要一个类似2个用户共有的Session变量,这个变量可以随 用户/私聊/棋局 消失而消失.

3,Ajax应用需要频繁的访问一些常用的对象变量,这些变量状态最好不要频繁从数据库读取,比如下棋的双方要知道对方是谁,颜色,走棋/聊天的变化等等,即是对方个人的东西,又是我方需要知道的内容,这些状态一经创建,就要保留到用户离线为止.

4,相对精确判断离线的问题.

问题设想:
能不能创建一个类来实现一种Session一样的东东,对一个用户来说即可以单件模式创建,又可以指定的2个/几个用户在生存期共享?

可以用静态类的静态方法保证单件模式.返回一个实例来代替Session.这个办法类似设计模式里所说的享元模式或者某种工厂模式,叫他什么名字其实不重要,关键它很实用
.Net2.0以后提供了泛型,让实现这种模式更加方便,以下是精简的代码.

一,实体类:
  public class User
  {
  public User(string userId)
  {  
  }
  public string color;
  public string userId;
  public string userName;
  public string enmyUserName;
  public string enmyUserId;
  public string enmyColor;
  }
二.管理实体类的类,叫它静态工厂也可以,用Dictionary来管理构造参数和返回的类,保证第一次创建后以后不重复创建.
public static class UserManager
  {
  public static Dictionary<string, User> Users = new Dictionary<string, User>();
  public static User getUser(string UserId)
  {
  if (Users.ContainsKey(UserId))
  {
  return (Users[UserId]);
  }
  else
  {
  Users.Add(UserId, new User(UserId));
  }
  return (Users[UserId]);
  }
  }

三,使用办法:
得到一个User的实例.
string userId = Session["userId"].ToString();
User U = UserManager.getUser(userId);

这样你在全站访问User的时候,相当于在Session里访问,
U.userName相当于在Session["userName"] ,U.color相当于在Session["color"] 等等,编程方便许多,只用到了一个Session["userId"],其他都顺腾摸瓜出来了。

下面我们观察一下棋局/私聊的例子,是模拟两个用户共同创建的Session替代品
一,实体棋局类:
  public class board
  {
  public board(string redUserId, string grayUserId)
  {
  //构造函数,参数是两个用户Id.
  }
}
 二.管理实体类的类,保证两个人不重复创建了唯一的一个棋局/私聊
public static class boardManager
  {
  public static Dictionary<string, board> Boards = new Dictionary<string,board>();
  public static board getBoard(string redUserId, string grayUserId)
  {
  string Key = (Convert.ToInt32(redUserId) > Convert.ToInt32(grayUserId)) ? (redUserId + "_" + grayUserId) : (grayUserId + "_" + redUserId);  
  if (Boards.ContainsKey(Key) )
  {
  return (Boards[Key]);
  }
  else
  {
  Boards.Add(Key, new board(redUserId, grayUserId));
  }  
  return (Boards[Key]);
  }
  }
 三,使用办法:  
 board B = boardManager.getBoard(U.userId, U.enmyUserId);

然后你想得到这个B的什么属性方法都可以,而且你可以得到或者设置当前棋局的每个用户的状态,这些状态可以在下棋/私聊结束的时候控制销毁掉。

我还用这个办法结合Ajax相对精确的判断对方离线。具体做法:你猜?不难实现。

总结:

静态类/静态方法,在web开发里可以用来代替Session和Application全局变量,对于提高性能和编程方便大有好处。
让类的实例有合理的生存周期,是web开发面向对象的难点,多考虑静态和类实例的结合,对web开发极其有益。


技巧补充:
Lock(typeOf(静态类))
{

//连续多次修改静态类某些全局变量
}
这样可以保证在多用户共同修改的情况下,你的修改是连续的,锁定的。



------解决方案--------------------
星辰技术社区:www.netcsharp.cn,我们将帮您以最快的速度找到最佳的解决方案