欢迎投稿

今日深度:

重构—多种方法实现学生下机,重构实现学生

重构—多种方法实现学生下机,重构实现学生


    在设计学生下机这个功能的时候,参考了很多博客,觉得用职责链模式是很合适的,因为我们知道学生下机算消费余额的时候是按照上机时间来算的,准备时间、至少上机时间,这就产生三种情况。但是虽然想到了,但是却没有具体的去实现,还是懒惰的原因吧,我就写了一个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)

    熟练的使用设计模式会让我们更加容易编程,希望此文能帮到大家,不足之处还望多多指教。

 

 

www.htsjk.Com true http://www.htsjk.com/shujukunews/6542.html NewsArticle 重构—多种方法实现学生下机,重构实现学生 在设计学生下机这个功能的时候,参考了很多博客,觉得用职责链模式是很合适的,因为我们知道学生下机算消费余额的时候是按照上机时...
评论暂时关闭