在个人机房重构的过程中,使用设计模式比较少,所以借着这次机房合作的机会,又巧好承担了B层任务,所以希望多多尝试使用设计模式,希望从中得到锻炼。
定义了一种对多的依赖关系,让多个观察者对象同时监听某一个主题对象,让这个主题对象在状态发生变化时,会通知所有的观察者,使他们能够自动更新自己。
大家都知道在下机的过程中有三种方式,正常下机、强制选中下机、强制全部下机,而且判断卡下机同样需要三个方法。仔细考虑选择下机方式和下机过程有什么联系,在结合观察者模式,下机方式相当于通知者,而下机过程中的三个过程相当于三个具体的观察者。抱着尝试的心态,开始嵌套设计模式。首先最重要的还是UML图,毕竟一张图胜过前言万语!
在做的过程中发现一个问题就是下机过程中可能用到的三种方法有先后顺序,必须先满足卡号存在,然后在满足正在上机,最后才是真正的算消费下机。而观察者模式中,所有的观察者都是平等,不需要彼此之间关系的满足。如果不考虑这个问题其实用观察者模式也能实现,无非就是浪费一下程序运行时候的资源,当条件不满足下机条件时,继续进行判定操作,当然最后肯定是没有结果的。在这过程自己确是没有什么好的方法,而是使用一个全局的布尔变量,分别在三种方法执行前判断,符合则执行,否则退出,同样的缺点还是将三个方法各加载一遍。下面是其中的部分过程代码。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Entity;
using BLL;
using IDAL;
using Factory;
using System.Reflection;
namespace BLL {
/// <summary>
/// 抽象的通知者
/// </summary>
public abstract class BSubject
{
//活动列表
private IList<BObserver> observers = new List<BObserver>();
//增加
public void Attach(BObserver observer)
{
observers.Add(observer);
}
/// <summary>
/// 减少用户
/// </summary>
/// <param name="observer">访问者</param>
public void Detach(BObserver observer)
{
observers.Remove(observer);
}
/// <summary>
/// 通知
/// </summary>
/// <param name="eCard"></param>
public void Notity( string CardId)
{
foreach (BObserver o in observers)
o.BUpdate(CardId);
}
}//end BSubject
}//end namespace BLL
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Entity;
using System.Text;
namespace BLL {
/// <summary>
/// 抽象的观察者
/// </summary>
public abstract class BObserver {
protected string CardId;
public BObserver(string CardId)
{
this.CardId = CardId;
}
/// <summary>
/// 通知者中的方法
/// </summary>
/// <param name="eCard"></param>
public abstract bool BUpdate(string CardId);
}//end BObserver
}//end namespace BLL
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Entity;
using BLL;
using Factory;
using IDAL;
using System.Reflection;
namespace BLL {
/// <summary>
/// 判断卡号是否存在
/// </summary>
public class BOCardIsExist : BObserver {
public BOCardIsExist(string CardId)
: base(CardId)
{ }
ICommonFunction iCommonFunction = FactoryRoom.CreateCommonFunction();
/// <summary>
/// 通知者中的方法
/// </summary>
/// <param name="eCard"></param>
public override bool BUpdate(string CardId)
{
try
{
Entity.ECard eCard = new ECard();
eCard.CardId = CardId;
List<ECard> ecard = iCommonFunction.CardJudge(eCard);
//调用公共方法,验证卡号是否存在
if (ecard==null)
//如果为空,则不存在该卡号
{
return BOutLine.Judge = true;
throw new Exception("此卡号不存在,请重新查询");
//返回值为false
}
else
{
return BOutLine.Judge = false;
//返回值为true
}
}
catch (Exception)
{
throw new Exception ("操作失误,请重新操作");
}
}
}//end BOCardIsExist
}//end namespace BLL
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Entity;
using BLL;
using IDAL;
using System.Reflection;
using Factory;
namespace BLL {
/// <summary>
/// 结算消费金额,并更新
/// </summary>
public class BOCountCash : BObserver {
public BOCountCash(string CardId)
: base(CardId)
{ }
IOutLine iOutLine = FactoryRoom.CreateOutLine();
/// <summary>
/// 获取消费分钟数
/// </summary>
private int _consumeTime;
public BPrepareTime m_BPrepareTime;
/// <summary>
/// 通知者中的方法
/// </summary>
/// <param name="eCard"></param>
public override bool BUpdate(string CardId)
{
try
{
if (BOutLine.Judge == false)
{
return BOutLine.Judge = false;
}
else
{
ELine eLine = new ELine();
//实例化一个上机实体
eLine.CardId = CardId;
ECard eCard = new ECard();
eCard.CardId = CardId;
List<ELine> eline = iOutLine.QueryStartLineTime(eLine);
//获取此卡的上机时间
string start = eline[0].OnLineDate;
DateTime endtime = DateTime.Now; //endtime是计算机的系统时间
DateTime starttime = Convert.ToDateTime(start);
TimeSpan t1 = endtime - starttime; //求从开始上机到下机的时间差
string subtractString = t1.Minutes.ToString();
//将求得时间差转变为分钟数
int subtract = Convert.ToInt32(subtractString);
//将求的时间差转变为整型
BCountCash bPrepareTime = new BPrepareTime();
BCountCash bLeastTime = new BLeastTime();
BCountCash bMoreTime = new BMoreTime();
bPrepareTime.SetSuccessor(bLeastTime);
bLeastTime.SetSuccessor(bMoreTime);
decimal ConsumeCash = bPrepareTime.BCountMoney(subtract, eCard);
eLine.ConsumeCash = ConsumeCash;
//将求得消费金额赋值给上机实体
List<EOffInfo>offInfo = iOutLine.CountCash(eLine);
if (offInfo ==null)
//根据返回受影响的行数来判断
{
return BOutLine.Judge = true;
//如果大于0,则证明操作成功
}
else
{
return BOutLine.Judge = false;
//否则的则是没有成功插入
}
}
}
catch (Exception)
{
throw new Exception ("操作失误,请重新操作!");
}
}
/// <summary>
/// 获取消费分钟数
/// </summary>
public int ConsumeTime{
get{
return _consumeTime;
}
set{
_consumeTime = value;
}
}
}//end BOCountCash
}//end namespace BLL
//客户段
namespace BLL
{
public class BOutLine
{
public static bool Judge;
public void Normal(string CardId)
{
//正常的下机必须检查
NormalOutLine normaloutline = new NormalOutLine();
BOCardIsExist boCardIsExist = new BOCardIsExist(CardId);
BOLineIsExist boLineIsExist = new BOLineIsExist(CardId);
BOCountCash boCountCash = new BOCountCash(CardId);
normaloutline.Attach(boCardIsExist);
normaloutline.Attach(boLineIsExist);
normaloutline.Attach(boCountCash);
normaloutline.Notity(CardId);
//判断返回的值是true,还是false,
}
如果没有这个判断的先后顺序,下机模式使用观察者模式恰到好处,可是如何解决这个问题,自己还没有特别好的方法。但是有一点就是职责链模式中有一个限定级别的方法,如果将两种模式结合一下,可能会解决这个问题。目前还只是一种想法,还需要自己后续的实践。
其实添加上了观察者模式过程中,才发觉下机使用观察者模式有点欠妥当。但是有一点必须承认,如果要是当初压根就没想添加观察者模式,怎会发现不妥当,所以从这件事最大感受不能只看别人怎么做,亲自尝试一下,多思考一下,总有自己的收获,而这些东西刚刚好就是最宝贵的财富!
菜鸟一只,如有理解偏颇之处,还请各位大神斧正,不胜感激!