机房重构利用策略模式+简单工厂实现消费金额的计算

时间:2021-01-18 22:00:30

在做第一次机房收费系统中,有一项很令人头疼的事情,那就是临时用户的问题,在结账的时候,我们需要考虑该用户是固定用户还是临时用户,原来在用VB6.0做的时候,如果我们实现了这个功能,那么在代码中会出现很多的IF....else 语句,同时,我们必须要调用数据设定窗体中的数据,这样的话,会很麻烦,写出来的代码也会很乱,如今学习了设计模式,我们可以利用策略模式来实现对不同用户的消费金额进行计算。将不同的类型用户所用到的不同算法封装到子类中去,同时与简单工厂结合起来,来实现对不同子类的实例化。这样在很大程度上实现了解耦,同时减少了我们U层代码的压力。

具体实现如下:

策略模式中的context类,在这个类中要声明我们所需要赋值和使用的参数,同时定义一个简单工厂的函数来实现对不同子类的实例化。

Public Class CountContext
    Dim cs As CountSuper '声明一个CountSuper对象
    '声明必要的参数属性

    '消费时间属性
    Private Allconsume_time As Decimal
    Public Property Allconsumetime As Decimal
        Set(value As Decimal)
            Allconsume_time = value
        End Set
        Get
            Return Allconsume_time
        End Get
    End Property

    ''' <summary>
    ''' 固定用户一小时费用
    ''' </summary>
    ''' <remarks></remarks>
    Private fixUser_CashOne As Decimal

    Public Property fixUserCashOne As Decimal
        Set(value As Decimal)
            fixUser_CashOne = value
        End Set
        Get
            Return fixUser_CashOne
        End Get
    End Property

    ''' <summary>
    ''' 临时用户半小时费用
    ''' </summary>
    ''' <remarks></remarks>
    Private tempUser_CashHalf As Decimal
    Public Property tempUserCashHalf As Decimal
        Set(value As Decimal)
            tempUser_CashHalf = value
        End Set
        Get
            Return tempUser_CashHalf
        End Get
    End Property

    ''' <summary>
    ''' 总共消费金额
    ''' </summary>
    ''' <remarks></remarks>
    Private allCash_Count As Decimal
    Public Property allCashCount As Decimal
        Set(value As Decimal)
            allCash_Count = value
        End Set
        Get
            Return allCash_Count
        End Get
    End Property
    Public Sub CountContext(ByVal type As String)
        Select Case type
            Case "固定用户"
                Dim cs0 = New FixUserCashCount()
                cs = cs0
                Exit Select
            Case "临时用户"
                Dim cs1 = New tempUserCashCount()
                cs = cs1
                Exit Select
        End Select
    End Sub
    '声明方法来让具体子类对象去执行具体的函数
    Public Sub CountAllCash()  '供客户端调用的方法
        cs.CashCount(Me) '返回消费总金额
    End Sub
End Class
策略模式中的抽象类:抽象类实现了对不同子类的封装,是子类继承父类,实现多态。在这里抽象类中定义一个提供计算消费金额的抽象一个方法。

Public MustInherit Class CountSuper
    ''' <summary>
    ''' 此为策略模式中用到的计算金额的抽象类
    ''' </summary>
    ''' <param name="count">countContext对象</param>
    ''' <remarks></remarks>
    Public MustOverride Sub CashCount(ByVal count As CountContext)

End Class
子类:Inherit CountSuper

固定用户子类

Public Class FixUserCashCount : Inherits CountSuper
    Public Overrides Sub CashCount(count As CountContext)
        '计算消费总金额
        count.allCashCount = -Int(-(count.Allconsumetime / 60)) * count.fixUserCashOne ’实现父类的方法
    End Sub
End Class

临时用户子类:

Public Class tempUserCashCount : Inherits CountSuper
    Public Overrides Sub CashCount(count As CountContext)
        count.allCashCount = -Int(-(count.Allconsumetime / 30)) * count.tempUserCashHalf
    End Sub
End Class

以上是在B层实现的各个方法,经过这些工作后,我们在U层只需要为context中需要的各个参数赋值后,直接调用其中的CountAllCash()方法即可。

原来做过通过状态模式计算学生的消费时间,这两个模式确实很像,它们从外表看类图是一

模一样的,只是状态模式在各个子类中要指明下一个执行的子类。二者本质上没有太大区别。

刚刚经过了设计模式的讨论会,我们知道策略模式是一种最基础的模式,它其中涉及到的关系很普遍,只包括了一个聚合和一个继承,而这两种关系也是我们设计模式中最常用的的,最核心的两种关系,通过原来的讨论我们发现很多的模式都可以通过转换而形成策略模式,所以掌握好策略模式对学习其他的设计模式还是很必要的。