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

时间:2021-09-04 21:58:49

前言:

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

策略模式:

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

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

职责链模式:

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

好处:

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

注意:

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

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

部分代码:

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

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

总结:

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