重构—多种方法实现学生下机,重构实现学生
在设计学生下机这个功能的时候,参考了很多博客,觉得用职责链模式是很合适的,因为我们知道学生下机算消费余额的时候是按照上机时间来算的,准备时间、至少上机时间,这就产生三种情况。但是虽然想到了,但是却没有具体的去实现,还是懒惰的原因吧,我就写了一个SQL函数,这样当学生下机时直接D层调用这个函数就可以了,直接返回消费时间、消费金额和余额,函数代码少,好实现,这就是当时的想法,可是验收却没通过,偷懒是不行滴,还是好好的设计吧。
首先我们要下机功能实现需要哪些条件,一个正在上机的卡号,这就需要我们首先验证这个卡号是否存在、或者已经注销、或者未上机,这些搞清楚进行下一步,判断消费时间——>下机时间-上机时间,看符合哪种收费方式,然后进行运算就好了。了解了需求,下面是我用触发器+数据库函数和职责链模式+策略模式分别实现的学生下机功能。
触发器实现下机时间的自动填充,消费时间的自动计算,余额的自动计算和在卡表中的自动更新
<span style="font-size:24px;">USE [MyDB]
GO
/****** Object: Trigger [dbo].[t_linelog] Script Date: 02/13/2015 15:02:09 ******/
SET ANSI_NULLS ON
GO
SETQUOTED_IDENTIFIER ON
GO
ALTER trigger[dbo].[t_linelog]
on [dbo].[Linelog]after insert, update
as
--声明变量
declare @linelogidint,@cardno varchar(10),@consumetime int,@consumecash int
select@linelogid=id,@cardno =CardNO frominserted
begin
--status改变则更新linelog
if update(status)
--更新下机时间
update Linelog
set
OffTime=GETDATE(),OffDate =GETDATE ()
where ID =@linelogid
--计算消费时间
update Linelog
set
ConsumeTime=DateDiff("MINUTE", OnTime, OffTime) + DateDiff("MINUTE" , OnDate,OffDate)
where ID =@linelogid
--调用函数,计算消费金额
update Linelog
set
ConsumeCash=dbo.f_ConsumeCash (@linelogid )
where ID =@linelogid
--更新卡中余额
update Card
set
Cash =card.Cash-Linelog .ConsumeCash
from Card left joinLinelog on Card .CardNO =Linelog .CardNO
where ID =@linelogid
END</span>数据库函数计算消费金额
<span style="font-size:24px;">USE [MyDB] GO /****** Object: UserDefinedFunction[dbo].[f_ConsumeCash] Script Date:02/12/2015 20:10:38 ******/ SET ANSI_NULLS ON GO SETQUOTED_IDENTIFIER ON GO ALTER function[dbo].[f_ConsumeCash](@linelogid int) returns int as begin --声明变量 declare @preparetimeint,@leasttime int,@unittime int, @rate int,@tmprateint, @cardtypevarchar(10), @consumecashint,@cash int, @consumetimeint,@cardno varchar(10) --给变量赋值 select @preparetime=PrepareTime,@leasttime=LeastTime,@unittime=UnitTime, @rate=Rate,@tmprate=tmpRatefrom BasicData select@cardtype=cardtype from Card where CardNO =@cardno select @consumetime=consumetime,@cardno=CardNO fromLinelog where ID =@linelogid --判断用户类别 if @cardtype ='固定用户' set @cash =@rate else set @cash=@tmprate --计算消费金额 if @consumetime<@preparetime set @consumecash=0 else if @consumetime<@leasttime set @consumecash=@leasttime *@cash else set @consumecash=(@consumetime/@unittime) *@cash --返回消费金额 return @consumecash End GO /****** Object: UserDefinedFunction[dbo].[f_ConsumeCash] Script Date:02/12/2015 20:10:38 ******/ SET ANSI_NULLS ON GO SETQUOTED_IDENTIFIER ON GO ALTER function[dbo].[f_ConsumeCash](@linelogid int) returns int as begin --声明变量 declare @preparetimeint,@leasttime int,@unittime int, @rate int,@tmprateint, @cardtypevarchar(10), @consumecashint,@cash int, @consumetimeint,@cardno varchar(10) --给变量赋值 select @preparetime=PrepareTime,@leasttime=LeastTime,@unittime=UnitTime, @rate=Rate,@tmprate=tmpRatefrom BasicData select@cardtype=cardtype from Card where CardNO =@cardno select @consumetime=consumetime,@cardno=CardNO fromLinelog where ID =@linelogid --判断用户类别 if @cardtype ='固定用户' set @cash =@rate else set @cash=@tmprate --计算消费金额 if @consumetime<@preparetime set @consumecash=0 else if @consumetime<@leasttime set @consumecash=@leasttime *@cash else set @consumecash=(@consumetime/@unittime) *@cash --返回消费金额 return @consumecash End</span>
下面是职责链+策略模式实现下机功能,首先再了解一下这两个模式的结构图,如图,是和我的代码匹配的模式结构图:
策略模式结构图
职责链模式结构图
职责链模式计算消费时间
U层调用代码:
<span style="font-size:24px;">'职责链模式计算消费时间 Dim ontimecount AsNew BLL.OnLineTimeCountBLL linelog.ConsumeTime= ontimecount.CostTime(time, endatabasic:=BLL.DataBasicBLL.mydatabasic)</span>
(这里的time是我在数据库中利用触发器得到的学生从上机到下机过程中所经历的具体时间)
计算时间的函数,调用职责链模式,和外观类似
<span style="font-size:24px;">Public ClassOnLineTimeCountBLL
Public m_TimeHanderBLL As TimeHanderBLL
''' <summary>
''' 职责链处理,上机时间的计算
''' </summary>
''' <param name="time ">上机记录实体</param>
''' <param name="endatabasic">基本数据实体</param>
Public Function CostTime(ByVal time AsInteger, ByVal endatabasic As List(Of Entity.DataBasicEntity)) As Integer
Dim Bpreparetime As NewPrePareTimeHnaderBLL(endatabasic)
Dim Bleasttime As NewLeastTimeHanderBLL(endatabasic)
Dim Bunittime As NewUnitTimeHanderBLL(endatabasic)
Bpreparetime.SetSucessor(Bleasttime)
Bleasttime.SetSucessor(Bunittime)
Return Bpreparetime.HandleTime(time)
End Function
End Class</span>至少上机时间
<span style="font-size:24px;">Public ClassLeastTimeHanderBLL
Inherits TimeHanderBLL
Private leastTime As Integer
''' <summary>
''' 判断上机时间是否小于至少上机时间,否则转到下一位
''' </summary>
''' <paramname="time"></param>
Public Overrides Function HandleTime(ByValtime As Integer) As Integer
If time < leastTime Then
Return time
Else
Return successor.HandleTime(time)
End If
End Function
''' <summary>
''' 构造函数,传入至少上机时间的值
''' </summary>
''' <paramname="endatabasic"></param>
Public Sub New(ByVal endatabasic As List(OfEntity.DataBasicEntity))
Me.leastTime =endatabasic.Item(0).LeastTime
End Sub
End Class</span>准备时间
<span style="font-size:24px;">Public ClassPrePareTimeHnaderBLL
Inherits TimeHanderBLL
Private Preparetime As Integer
''' <summary>
''' 判断上机时间是否小于准备时间,否则转到下一位继承者
''' </summary>
''' <paramname="time">时间</param>
Public Overrides Function HandleTime(ByValtime As Integer) As Integer
If time < Preparetime Then
Return time
Else
Return successor.HandleTime(time)
End If
End Function
''' <summary>
''' 构造函数,传入准备时间的值
''' </summary>
''' <paramname="endatabasic"></param>
Public Sub New(ByVal endatabasic As List(OfEntity.DataBasicEntity))
Me.Preparetime =endatabasic.Item(0).PrepareTime
End Sub
End Class</span>递增时间
<span style="font-size:24px;">Public ClassUnitTimeHanderBLL
Inherits TimeHanderBLL
Private unitTime As Integer
Public m_TimeHanderBLL As TimeHanderBLL
''' <summary>
''' 大于至少上机时间,返回实际消费时间
''' </summary>
''' <paramname="time"></param>
Public Overrides Function HandleTime(ByValtime As Integer) As Integer
Return Math.Abs(Int(time / unitTime) +1)
End Function
''' <summary>
''' 构造函数,传入单位递增时间的值
''' </summary>
''' <paramname="endatabasic"></param>
Public Sub New(ByVal endatabasic As List(OfEntity.DataBasicEntity))
Me.unitTime =endatabasic.Item(0).UnitTime
End Sub
End Class</span>
策略模式计算消费金额
上下文Context,对一个策略进行引用
<span style="font-size:24px;">Public ClassCashContextBLL
Public myCashSuperBLL As CashSuperBLL
''' <summary>
''' 调用抽象类的消费金额计算方法,得出消费金额
''' </summary>
''' <paramname="Time"></param>
Public Function GetResult(ByVal Time AsInteger) As Integer
Return myCashSuperBLL.CostCash(Time)
End Function
''' <summary>
''' 利用反射,根据卡号类型选择要实例化的类
''' </summary>
''' <paramname="CardType">卡类型</param>
Public Sub New(ByVal CardType As String)
Dim strInstance As String ="BLL.Cash" + CardType + "BLL"
myCashSuperBLL =CType(Assembly.Load("BLL").CreateInstance(strInstance), CashSuperBLL)
End Sub
End Class</span>
具体的结算方法1
<span style="font-size:24px;">Public ClassCashFixBLL : Inherits CashSuperBLL
''' <summary>
''' 计算固定用户消费金额
''' </summary>
''' <paramname="Time"></param>
Public Overrides Function CostCash(Time AsInteger) As Integer
Dim databasic As New List(OfEntity.DataBasicEntity)
Dim rate As Integer =BLL.DataBasicBLL.mydatabasic.Item(0).Rate
Return rate * Time
End Function
End Class</span>具体的结算方法2
<span style="font-size:24px;">Public ClassCashTmpBLL : Inherits CashSuperBLL
''' <summary>
''' 计算临时用户消费金额
''' </summary>
''' <paramname="Time"></param>
Public Overrides Function CostCash(Time AsInteger) As Integer
Dim databasic As New List(OfEntity.DataBasicEntity)
Dim Tmprate As Integer =BLL.DataBasicBLL.mydatabasic.Item(0).tmpRate
Return Tmprate * Time
End Function
End Class</span>U层调用
'根据以上时间,应用策略模式计算消费金额 Dim CardType AsString Select Case showmessage.Item(0).type Case "固定用户" CardType = "Fix" Case "临时用户" CardType = "Tmp" Case Else CardType ="" End Select '实例化类CashContextBLL,传入用户类型 Dim cashcontext As NewCashContextBLL(CardType) '调用策略模式计算出消费金额并赋值给上机记录实体 checkcard.concash =cashcontext.GetResult(linelog.ConsumeTime)
熟练的使用设计模式会让我们更加容易编程,希望此文能帮到大家,不足之处还望多多指教。
本站文章为和通数据库网友分享或者投稿,欢迎任何形式的转载,但请务必注明出处.
同时文章内容如有侵犯了您的权益,请联系QQ:970679559,我们会在尽快处理。