机房重构——下机(职责链模式+策略模式)

前言:

说起机房重构的下机自己都有点不好意思了,不想提起自己的那点“小事”。要做上下机的时候自己整个人都很不开心,感觉自己搞不定它们,有种压抑感,还略带了点小情绪,不想弄,其实都是自己把自己吓到了。只要静下心来,开开心心的去想思路,看代码,没有什么做不出来,学不会的。保持乐观的心态,比什么都重要。

策略模式:

它定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的客户。直白的说,策略模式是一种定义一系列算法的方法,从概念上看,所有这些算法完成的都是相同的工作,只是实现不同,它可以以相同的方式调用所有的算法,减少了各种算法类与使用算法类之间的耦合。


职责链模式:

职责链模式使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。

好处:

接收者和发送者都没有对方的明确信息,且链中的对象自己也并不知道链的结构。结果是职责链可简化对象的相互连接,它们仅需要保持一个指向其后继者的引用,而不需保持它所有的候选接受者的引用,大大降低了耦合度。可以随时随地增加或修改处理一个请求的结构,增强了给对象指派职责的灵活性。

注意:

一个请求极有可能到了链的末端都得不到处理,或者因为没有正确配置而得不到处理,所以需要事先考虑全面。


部分代码:

U层:

'下机
    Private Sub btnDown_Click(sender As Object, e As EventArgs) Handles btnDown.Click
        '判断卡号是否为空
        If txtCardno.Text = "" Then
            MsgBox("请输入卡号!", 0, "提示")
            txtCardno.Focus()
            Exit Sub
        End If
        '判断卡号是否存在或使用
        Dim facade As New Facade.OnLineFacade
        Dim card As New Entity.OnLineEntity
        Dim table As DataTable

        card.CardNo = txtCardno.Text.Trim
        table = facade.SelectCardNo(card)

        If table.Rows.Count = 0 Then
            MsgBox("该卡号不存在!", 0, "提示")
            txtCardno.Text = ""
            txtCardno.Focus()
            Exit Sub
        Else
            '判断卡号是否在上机(online)
            Dim fac As New Facade.OnLineFacade
            Dim line As New Entity.OnLineEntity
            Dim onlinetable As New DataTable

            line.CardNo = txtCardno.Text.Trim
            onlinetable = fac.SelectoOn(line)

            If onlinetable.Rows.Count = 0 Then
                MsgBox("该卡未处于上机状态,无需下机!", 0, "提示")
                txtCardno.Text = ""
                txtCardno.Focus()
                Exit Sub
            Else
                '获取T_Card表中对应上机卡号的金额和类型
                Dim cash As String
                Dim type As String
                cash = table.Rows(0).Item(2)
                type = table.Rows(0).Item(3).ToString.Trim
                '获取上机时间
                line.OnLineDate = Format(onlinetable.Rows(0).Item(3))
                line.OnLineTime = onlinetable.Rows(0).Item(4).ToString
                '给上机记录实体赋下机时间
                line.OffLineDate = Format(DateTime.Now, "yyyy/MM/dd")
                line.OffLineTime = Format(DateTime.Now, "HH:mm:ss")
                '查询基本数据
                Dim Basefac As New Facade.OnLineFacade
                Dim data As New Entity.BaseDataEntity
                Dim basetable As New DataTable

                basetable = Basefac.SelectBaseData(data)
                data.UnitTime = basetable.Rows(basetable.Rows.Count - 1).Item(3)
                data.LeastTime = basetable.Rows(basetable.Rows.Count - 1).Item(4)
                data.PrepareTime = basetable.Rows(basetable.Rows.Count - 1).Item(5)
                '获取消费时间
                Dim consumeTime As Integer
                Dim BLLObject As New BLL.OnlineTimeCountBLL
                consumeTime = BLLObject.costTime(data, line)
                line.ConsumeTime = consumeTime
                '根据获得的上机时间,利用策略模式计算消费金额 
                If type = "固定用户" Then
                    type = "Vip"
                Else
                    type = "Tmp"
                End If
                
          
                '实例化类OL_CashContextFacade,传入用户类型
                Dim cashcontext As New BLL.OL_CashContextBLL(type)
                '调用策略模式计算出余额并赋给consumecash
                Dim consumecash As Single = cashcontext.GetResult(line.ConsumeTime)
                '定义变量newcash,用于存放最新 的余额
                Dim newcash As Single = CSng(cash.ToString) - CSng(consumecash)

                '更新OnLine表,更新卡表的余额
                line.ConsumeCash = consumecash
                line.Cash = newcash

                '获取学生表中的信息
                Dim stufac As New Facade.OnLineFacade
                Dim stuinfo As New Entity.OnLineEntity
                Dim stutable As New DataTable
                Dim flag As Boolean
                stuinfo.CardNo = txtCardno.Text.Trim
                stutable = stufac.SelectStu(stuinfo)

                flag = facade.offline(line)
                If flag = True Then
                    MsgBox("下机成功!", 0, "提示")
                    txtCardno.Text = line.CardNo
                    txtType.Text = table.Rows(0).Item(3)
                    txtStudentno.Text = onlinetable.Rows(0).Item(1)
                    txtName.Text = stutable.Rows(0).Item(1)
                    txtDepartment.Text = stutable.Rows(0).Item(3)
                    txtSex.Text = stutable.Rows(0).Item(2)
                    txtUpdate.Text = line.OnLineDate
                    txtUptime.Text = line.OnLineTime
                    txtDowndate.Text = line.OffLineDate
                    txtDowntime.Text = line.OffLineTime
                    txtCount.Text = newcash
                    txtConsumetime.Text = consumeTime
                    txtConsumcash.Text = consumecash
                    line.IsOff = "下机"
                    '统计上机人数,更新上机人数
                    'line.CardNo = txtCardno.Text.Trim
                    onlinetable = fac.SelectoOn(line)
                    lblCount.Text = onlinetable.Rows.Count
                Else
                    MsgBox("下机失败!", 0, "提示")
                End If
            End If
        End If
    End Sub

B层:


职责链模式:

OL_TimeHandler

'定义一个处理请求的接口
Public MustInherit Class OL_TimeHandler
    Protected successor As OL_TimeHandler
    Public Sub setsuccessor(ByVal successor As OL_TimeHandler)
        Me.successor = successor '设置继承者
    End Sub
    Public MustOverride Function HandleTime(onlinetime As Integer) As Integer '处理请求的抽象类
End Class
                                                                  

OL_PrepareTimeHandlerBLL

'准备时间处理类
Public Class OL_PrepareTimeHandlerBLL : Inherits OL_TimeHandler
    Private preparetime As Integer
    Public Sub New(ByVal data As Entity.BaseDataEntity)
        '构造函数,传入准备时间的值
        Me.preparetime = CInt(data.PrepareTime)
    End Sub
    Public Overrides Function HandleTime(onlinetime As Integer) As Integer
        If onlinetime <= preparetime Then
            Return 0 'if 函数判断上机时间是否在处理范围内,在则返回0,不在转到下一个处理类
        Else
            Return successor.HandleTime(onlinetime) '转到下一位继承者
        End If
    End Function

OL_LeastTimeHandlerBLL

'至少上机时间处理类
Public Class OL_LeastTimeHandlerBLL : Inherits OL_TimeHandler
    Private leasttime As Integer
    Public Sub New(ByVal data As BaseDataEntity)
        Me.leasttime = CInt(data.LeastTime)
    End Sub
    Public Overrides Function HandleTime(onlinetime As Integer) As Integer
        If onlinetime <= leasttime Then  '上机时间如果小于至少上机时间,返回上机时间
            Return leasttime
        Else  '否则转到下一位继承者
            Return successor.HandleTime(onlinetime)
        End If

OL_UnitTimeHandlerBLL

'单位时间处理类
Public Class OL_UnitTimeHandlerBLL : Inherits OL_TimeHandler
    Private unittime As Integer
    Public Sub New(ByVal data As BaseDataEntity)
        Me.unittime = CInt(data.UnitTime) 'CInt函数将数值转换成函数
    End Sub
    Public Overrides Function HandleTime(onlinetime As Integer) As Integer
        Return Math.Abs(Int(-onlinetime / unittime)) * unittime
        'int是将一个数值乡下取整为最接近的整数函数,取整函数
        'abs函数返回指定数值的绝对值
    End Function

OL_OnlineTimeCountBLL

'计算出上下机时间差,然后把结构返回给职责链处理
Public Class OL_OnlineTimeCountBLL
    Public Function costTime(data As Entity.BaseDataEntity, line As Entity.OnLineEntity) As Integer
        '实例化类,通过构造函数,传递参数
        Dim bPrepareTime As New OL_PrepareTimeHandlerBLL(data)
        Dim bLeastTime As New OL_LeastTimeHandlerBLL(data)
        Dim bStepTime As New OL_UnitTimeHandlerBLL(data)

        bPrepareTime.setsuccessor(bLeastTime) '设置职责链继承者即后继承者
        bLeastTime.setsuccessor(bStepTime)
        '计算上下机时间差
        Dim onlinetime As Integer
        onlinetime = DateDiff("n", line.OnLineTime, line.OffLineTime) + DateDiff("n", line.OnLineDate, line.OffLineDate)
        '职责链处理,返回上机时间
        Return bPrepareTime.HandleTime(onlinetime)
    End Function


End Class

策略模式:

OL_CashContextBLL:

通过传入的卡的类型,对具体的固定用户或临时用户的处理算法进行选择

'通过传入的卡的类型,对具体的固定用户或临时用户的处理算法进行选择
Imports System.Reflection
'应用简单工厂模式,通过传入的卡的类型,来选择具体用哪个算法
Public Class OL_CashContextBLL
    Private cashsuper As OL_CashSuperBLL '定义抽象类
    Public Sub New(ByVal Type As String)
        '应用反射技术根据卡号类型自动选择应该实例化的类
        Dim strInstance As String = "BLL.OL_Cash" + Type + "BLL"
        cashsuper = CType(Assembly.Load("BLL").CreateInstance(strInstance), OL_CashSuperBLL)

    End Sub
    Public Function GetResult(ByVal onlinetime As String) As Single
        '调用相关的消费处理类计算收费方法

        Return cashsuper.GetConsumeCash(onlinetime)
    End Function

End Class

OL_CashSuperBLL:

定义算法的接口

'定义算法接口,抽象类
Public MustInherit Class OL_CashSuperBLL
    '根据上机时间、卡的类型,计算出消费金额,抽象方法。
    Public MustOverride Function GetConsumeCash(ByVal online As Integer) As Single
End Class
OL_CashVipBLL:

计算固定用户消费金额

'具体策略类,计算固定用户消费金额,封装了具体的算法或行为,继承于OL_CashSuperBLL
Public Class OL_CashVipBLL : Inherits OL_CashSuperBLL
    Dim queryBasedate As New BaseDataBLL '实例化查询基础数据
    Dim ebasedate As New Entity.BaseDataEntity
    Dim table As DataTable
    Dim VipHourCash As Single '定义变量存放固定用户每小时费用
    Public Overrides Function GetConsumeCash(onlinetime As Integer) As Single
        table = queryBasedate.selectBaseData(ebasedate)
        VipHourCash = table.Rows(table.Rows.Count - 1).Item(1) '查询数据库中对于固定用户的费用
        Dim consumecash As Single
        consumecash = CSng(onlinetime) * CSng(VipHourCash / 60) '计算消费金额
        Return consumecash
    End Function

End Class
OL_CashTmpBLL:

计算临时用户消费金额

'计算临时用户消费金额
Public Class OL_CashTmpBLL : Inherits OL_CashSuperBLL

    Dim queryBaseDate As New BaseDataBLL '实例化查询基础数据
    Dim ebasedate As New Entity.BaseDataEntity
    Dim table As DataTable
    Dim TemHourCash As Single '定义变量存放临时用户每小时费用
    Public Overrides Function GetConsumeCash(onlinetime As Integer) As Single
        '查询数据库中对于临时用户的费用
        table = queryBaseDate.selectBaseData(ebasedate)
        TemHourCash = table.Rows(table.Rows.Count - 1).Item(2)
        '计算消费金额
        Dim consumecash As Single
        consumecash = CSng(onlinetime) * CSng(TemHourCash / 60)
        Return consumecash
    End Function
End Class

D层:

利用存储过程pro_OffLine

 '下机
    Public Function offinsert(ByVal line As Entity.OnLineEntity) As Boolean Implements IOnLine.offinsert
        Dim sql As String
        Dim sqlParams As SqlParameter() = {New SqlParameter("@cardno", line.CardNo),
                                           New SqlParameter("@offdate", line.OffLineDate),
                                           New SqlParameter("@offtime", line.OffLineTime),
                                           New SqlParameter("@consumetime", line.ConsumeTime),
                                           New SqlParameter("@consumecash", line.ConsumeCash),
                                           New SqlParameter("@cash", line.Cash),
                                           New SqlParameter("@isoff", "下机")
                                        }
        sql = "pro_OffLine"
        Dim flag As Boolean
        flag = sqlhelper.ExecAddDelUpdate(sql, CommandType.StoredProcedure, sqlParams)
        Return flag
    End Function
End Class

存储过程:

CREATE PROCEDURE [dbo].[pro_OffLine]
	-- Add the parameters for the stored procedure here
	@cardno varchar(10),
	@offdate date,
	@offtime time(7),
	@consumetime varchar(10),
	@consumecash  numeric(18,1),
	@cash  varchar(50),
	@isoff char(5)
AS
BEGIN
	update T_OnLine set offLineDate=@offdate ,offLineTime=@offtime,consumeTime=@consumetime,consumeCash=@consumecash ,isOff =@isoff where cardNo =@cardno 
	update T_Card set cash=cash-@consumecash where cardNo=@cardno 
   
END

注:创建好存储过程并执行后,再次打开存储过程create procedure将会变成alter procedure


总结:

在写这部分的时候,首先要理清楚思路,想好要判断哪些条件,做好准备工作,然后再动手写代码,不然写到一半很容易会思维混乱。也可以站在巨人的肩膀上,多多向大神们学习。(*^__^*) 嘻嘻……我也是。。。












评论 33
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值