策略模式的实例学习

时间:2021-01-22 14:39:07

现在合作开发机房收费系统,需要进一步地研究设计模式,发现真地用过了,不管用的好不好,理解起来会容易很多,收获的也大不一样。下面我就写写策略模式的使用。

1.什么时候使用策略模式?

策略模式的概念和UML图在之前的博客中写过,这里不再重复。主要想说一下什么时候使用策略模式。

策略模式是一种定义一系列算法的方法,从概念上看,所有这些算法完成的都是相同的工作,只是实现不同,它可以以相同的方式调用所有的算法,减少各种算法类与使用算法类之间的耦合。在机房收费系统中我在计算固定用户和临时用户的上机消费的地方 使用了策略模式。

2.机房收费系统中使用策略模式的UML图

在外观层中类图为:

策略模式的实例学习

在BLL层中的类图为:

策略模式的实例学习

3.实现的代码

U层:

......
        dt1 = subBasicValidate.ExistCardNo(enCard.CardNo)   '得到卡的类型        Dim csuper As CashText = New CashText(dt1.Rows(0)(3))  '根据传入的参数决定实例化哪一个?        Dim cash As Decimal        cash = csuper.GetResult(enCard.CardNo)
Facade层:

Public Class CashText
Dim consumeCash As BLL.CashSuperBLL = Nothing
Sub New(ByVal cardType As String)
Select Case cardType
Case "固定用户"
Dim confirmCash As BLL.ConfirmUser = New BLL.ConfirmUser
consumeCash = confirmCash

Case "临时用户"
Dim tmpCash As BLL.TmpUser = New BLL.TmpUser
consumeCash = tmpCash
End Select
End Sub

Public Function GetResult(ByVal cardNo As String) As Decimal
Return consumeCash.ConsumeCash(cardNo)
End Function
End Class
B层:

Public MustInherit Class CashSuperBLL
''' <summary>
''' 计算出消费金额
''' </summary>
''' <param name="cardNo">卡号</param>
''' <returns>Decimal</returns>
''' <remarks></remarks>
Public MustOverride Function ConsumeCash(ByVal cardNo As String) As Decimal
End Class

Public Class ConfirmUser
Inherits CashSuperBLL
''' <summary>
''' 计算一个固定用户类型的卡号所花费的钱
''' </summary>
''' <param name="cardNo">卡号</param>
''' <returns>Decimal</returns>
''' <remarks></remarks>
Public Overrides Function ConsumeCash(cardNo As String) As Decimal
Dim subBasicData As New BLL.SubUsersManagerBLL
Dim subOnOff As New BLL.SubOnOffBLL
Dim dt As New DataTable
Dim dt1 As New DataTable

Dim unitPrice As Decimal
Dim onTime As DateTime
Dim offTime As DateTime
Dim interval As Integer
Dim n As Integer
Dim f As Single

dt = subBasicData.SelectBasicData() '从基本数据表中查询出固定用户的单价。
dt1 = subOnOff.SelStuOnOff(cardNo) '查询该卡号的上下机记录
unitPrice = dt.Rows(0)(0)
onTime = Convert.ToString(dt1.Rows(0)(1))
offTime = Convert.ToString(dt1.Rows(0)(3))

interval = DateDiff(DateInterval.Second, onTime, offTime) '计算出上机和下机之间的时间差

If interval >= 0 And interval <= dt.Rows(0)("prepareTime") Then '时间差在0和准备时间之间则不收费
Return 0.0
ElseIf dt.Rows(0)("unitTime") <> 0 Then '保证分母不为零.
n = interval \ dt.Rows(0)("unitTime") '取整
f = interval Mod dt.Rows(0)("unitTime") '取余,判断余数大不大与最少上机时间,若大于则进。
If f >= dt.Rows(0)("leastTime") Then
n = n + 1
End If
Return n * unitPrice '单价*固定半小时费用
Else
MsgBox("分母不能为零", vbOKOnly, "温馨提示")
Return 0.0
End If
End Function
End Class
临时用户的算法跟固定用户只是单位时间费用的区别,这里不给出代码。

4.总结

每一遍学习设计模式,都有不同的收获。在这个模式的学习里:看到一句话很兴奋:“封装变化点”。联想之前的经验,感觉面向对象三大特征真是精辟。继承的是类中不会变化的地方,变化的地方写死了就没有灵活性了。通过封装变化点,让根据需求带来的变化应对自如。当然封装本身就很有学问。而多态,个人片面理解就是解决继承中的灵活使用子类的问题。