zoukankan      html  css  js  c++  java
  • 机房收费系统重构之策略模式

          一、前言

          前面我们学习了23种设计模式,只是一直没用过,这次机房重构就是让我们将学习的这些理论应用与实践。首先,机房收费的主要功能就是上机收费,一说的收费就会有针对普通用户和会员等,实行不同的收费方法,这时我们就须要用到策略模式了。

          二、回想

           策略模式定义了一系列的算法,并将每个算法封装起来,并且使它们还能够相互替换。策略模式让算法独立于使用它的客户而独立变化。

                     

    详见:设计模式 ( 十八 ) 策略模式Strategy(对象行为型)

          三、代码实现(为了方便,将整个下机过程的代码所有给出)

          1、U层中下机button的代码

        ''' <summary>
        ''' 下机功能
        ''' </summary>
        ''' <param name="sender"></param>
        ''' <param name="e"></param>
        ''' <remarks></remarks>
        Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
    
            Dim facadeSystem As New FacadeSystem
            Dim cardEntity As New CardEntity
    
            Try
                cardEntity.CardId = txtCardId.Text            '传參
    
                Dim returnOnList As ArrayList
    
                '调用外观,实现下机
                returnOnList = facadeSystem.StudentOff(cardEntity)
    
                '提出返回的数据
                Dim returnStudentEntity As StudentEntity
                Dim returnLineRecordEntity As LineRecordEntity
                Dim returnCardEntity As CardEntity
    
                returnStudentEntity = returnOnList.Item(0)
                returnLineRecordEntity = returnOnList.Item(1)
                returnCardEntity = returnOnList.Item(2)
    
                '显示学生信息
                txtStudentId.Text = returnStudentEntity.StudentId
                txtName.Text = returnStudentEntity.StudentName
                txtSex.Text = returnStudentEntity.Sex
                txtClass.Text = returnStudentEntity.Classes
                txtDepartment.Text = returnStudentEntity.Department
                txtExplan.Text = returnStudentEntity.Explain
                txtGrade.Text = returnStudentEntity.Grade
                '显示上机信息
                txtOnTime.Text = returnLineRecordEntity.OnTime
                txtOffTime.Text = returnLineRecordEntity.OffTime
                txtConsumeCash.Text = returnLineRecordEntity.ConsumeCash
                txtConsumeTime.Text = returnLineRecordEntity.ConsumeTime
                txtRemainCash.Text = returnCardEntity.RemainCash
    
                '显示上机人数
                lbOnPeople.Text = facadeSystem.RefreshOnPeople()
    
                '显示上机成功
                lbInformation.Text = "欢迎下次光临!"
    
            Catch ex As Exception
                MsgBox(ex.Message)
            End Try
    
        End Sub

          2、外观层代码

    		''' <summary>
    		''' 学生下机
    		''' </summary>
            Public Function StudentOff(ByVal cardEntity As CardEntity) As ArrayList
                Try
                    Dim cardBLL As New CardBLL
                    Dim returnCardEntity As New CardEntity
                    Dim returnBoolean As Boolean
    
                    '检查卡号是否存在
                    returnBoolean = cardBLL.QueryCard(cardEntity)
                    If Not returnBoolean Then
                        Throw New Exception("卡号不存在!")
                    End If
    
                    '检查该卡号是否正在上机
                    Dim lineRecordBll As New LineRecordBLL
    
                    returnBoolean = lineRecordBll.GetOffStatus(cardEntity)
                    If Not returnBoolean Then
                        Throw New Exception("该卡号还没上机!")
                    End If
    
                    '假设正在上机,就查到上机信息
                    Dim lineRecordEntity As New LineRecordEntity
    
                    lineRecordEntity = lineRecordBll.GetOff(cardEntity)
    
                    '查看基础数据设定
                    Dim basicDataEntity As New BasicDataEntity
                    Dim basicDataBll As New BasicDataBLL
    
                    basicDataEntity = basicDataBll.QueryAll()
    
                    '计算消费时间
                    Dim getDateBll As New GetDateBLL
                    Dim strPrepareTime As Double
                    Dim consumeTime As Double
    
                    lineRecordEntity.OffTime = getDateBll.GetSqlTime()                                                                      '获取下机时间
    
                    strPrepareTime = getDateBll.changeForHour(basicDataEntity.PrepareTime)                                                  '将准备时间转换为以小时为单位
                    consumeTime = getDateBll.TimeToHour(lineRecordEntity.OffTime) - getDateBll.TimeToHour(lineRecordEntity.OnTime)          '计算消费时间
    
                    '推断消费时间是否大于准备时间
                    If consumeTime < strPrepareTime Then
                        lineRecordEntity.ConsumeTime = "0.0"
                    Else
                        lineRecordEntity.ConsumeTime = CStr(consumeTime - strPrepareTime)
                    End If
    
                    '计算消费金额
                    Dim strStudentLevel As String = "GeneralUser"   '用来实例化详细的计费方法
                    Dim cashContext As CashContext
    
                    cashContext = New CashContext(strStudentLevel)   '实例化计费方法的类
                    lineRecordEntity.ConsumeCash = CStr(cashContext.GetResult(basicDataEntity, lineRecordEntity))
    
                    '其它參数
                    lineRecordEntity.OffDate = getDateBll.GetSqlDate()
                    lineRecordEntity.OffStatus = "正常下机"
                    lineRecordEntity.Local = System.Net.Dns.GetHostName().ToString
    
                    '记录为正常下机
                    lineRecordBll.AddOff(lineRecordEntity)
    
                    '改动卡上剩余金额
                    cardEntity = cardBLL.QueryAll(cardEntity)
                    cardEntity.RemainCash = CStr(CDbl(cardEntity.RemainCash) - CDbl(lineRecordEntity.ConsumeCash))
    
                    cardBLL.ModifyRemainCash(cardEntity)
    
                    '查询学生实体
                    Dim studentEntity As New StudentEntity
                    Dim studentBll As New StudentBLL
    
                    studentEntity.StudentId = cardEntity.CardId
                    studentEntity = studentBll.QueryAll(studentEntity)
    
                    '封装,传回
                    Dim returnOnList As New ArrayList
    
                    returnOnList.Add(studentEntity)
                    returnOnList.Add(lineRecordEntity)
                    returnOnList.Add(cardEntity)
    
                    Return returnOnList
    
                Catch ex As Exception
                    Throw
                End Try
    
            End Function
          3、cashContent类(相当于策略模式图中的Context类

    ''' <summary>
    	''' 策略模式中的context类,用一个详细计费方法来配置,维护一个对抽象计费方法对象的引用
    	''' </summary>
    	Public Class CashContext
    
    
    		''' <summary>
    		''' 声明一个计算消费金额的抽象类
    		''' </summary>
            Private cashSuper_ As CashSuper
            Private _strStudentLevel As String
    
    
    
    		''' <summary>
    		''' 声明一个计算消费金额的抽象类
    		''' </summary>
    		Private Property cashSuper() As CashSuper
    			Get
                    Return cashSuper_
    			End Get
    			Set(ByVal Value as CashSuper)
                    cashSuper_ = Value
    			End Set
    		End Property
    
    		''' <summary>
    		''' 通过构造方法,传入详细的收费策略
    		''' </summary>
            ''' <param name="strStudentLevel">初始化时,传入一个详细的收费策略</param>
    
            Sub New(strStudentLevel As String)
    
                Try
                    '利用反射创建详细的算法
                    Dim AssemblyName As String = "BLL"
                    Dim className As String = AssemblyName + ".BLL." + strStudentLevel + "ConsumeCash"
    
                    Me.cashSuper_ = CType(Assembly.Load(AssemblyName).CreateInstance(className), CashSuper)
    
                Catch ex As Exception
                    Throw
                End Try
    
            End Sub
    
            ''' <summary>
            ''' 依据不同的收费策略,获得计算结果
            ''' </summary>
            ''' <param name="basicDataEntity"></param>
            ''' <param name="lineRecordEntity"></param>
            ''' <returns></returns>
            ''' <remarks></remarks>
            Public Function GetResult(ByVal basicDataEntity As BasicDataEntity, ByVal lineRecordEntity As LineRecordEntity) As Double
    
                Try
                    Dim returnDouble As Double
                    returnDouble = cashSuper_.CountConsumeCash(basicDataEntity, lineRecordEntity)
    
                    Return returnDouble
    
                Catch ex As Exception
                    Throw
                End Try
    
    
            End Function
    
    
    	End Class ' CashContext

          4、CashSuper抽象类(相相当于策略模式图中的Strategy类

    	''' <summary>
        ''' 策略模式,封装计算方法的抽象类
    	''' </summary>
        Public MustInherit Class CashSuper
    
    
            ''' <summary>
            ''' 计算消费金额的计算方法
            ''' </summary>
            ''' <param name="lineRecordEntity">上机记录表的实体</param>
            ''' <param name="basicDataEntity">数据库数据表实体</param>
            Public MustOverride Function CountConsumeCash(ByVal basicDataEntity As BasicDataEntity, ByVal lineRecordEntity As LineRecordEntity) As Double
    
    
        End Class ' CashSuper

          5、GeneralUserConsumeCash类(相相当于策略模式图中的CreateStrategy类,详细收费方法

    	''' <summary>
    	''' 计算一般用户消费的方法
    	''' </summary>
    	Public Class GeneralUserConsumeCash
    		Inherits BLL.CashSuper
    
    
    	''' <summary>
    	''' 计算消费金额的计算方法
    	''' </summary>
            ''' <param name="lineRecordEntity">上机记录表的实体</param>
            ''' <param name="basicDataEntity">数据库数据表实体</param>
            Public Overrides Function CountConsumeCash(ByVal basicDataEntity As BasicDataEntity, ByVal lineRecordEntity As LineRecordEntity) As Double
    
                Try
                    Dim returnMoney As Double
                    Dim countTime As Integer           '表示多少个单位时间
                    Dim oneMinuteMoney As Double       '每分钟消费的钱
    
                    oneMinuteMoney = CDbl(basicDataEntity.UnitCash) / 60
    
                    '推断是否在规定上机时间内
                    If lineRecordEntity.ConsumeTime > basicDataEntity.LeastTime Then         '假设超过至少上机时间
                        '单位时间的个数=(消费时间-至少上机时间)/单位时间
                        countTime = CInt(Int((CDbl(Minute(CDate(lineRecordEntity.ConsumeTime))) - CDbl(basicDataEntity.LeastTime)) / basicDataEntity.UnitTime + 0.9999))
                        '消费金额=(单位时间个数*单位时间+至少上机时间)*每分钟消费的钱
                        returnMoney = (countTime * basicDataEntity.UnitTime + CDbl(basicDataEntity.LeastTime)) * oneMinuteMoney
                        Return returnMoney
                    Else                                                                     '假设没有超过至少上机时间
                        '至少上机时间乘以单位时间的钱
                        returnMoney = CDbl(basicDataEntity.LeastTime) * oneMinuteMoney
                        Return returnMoney
                    End If
    
                Catch ex As Exception
                    Throw
                End Try
    
            End Function
    
    
    	End Class ' GeneralUserConsumeCash

          四、讲解运行过程

           首先,将 "GeneralUser"传给变量strStudentLevel,作用是在Dim className As String = AssemblyName + ".BLL." + strStudentLevel + "ConsumeCash"这句话中,利用反射创建详细的收费方法,即普通用户的收费方法GeneralUserConsumeCash类。
           然后,调用cashContext.GetResult()方法,此方法又调用抽象类cashSuper的计算消费金额CountConsumeCash
    的方法,因为此方法在子类中被重写,所以最后运行详细收费类GeneralUserConsumeCash的CountConsumeCash方法,从而得出结果。

          五、总结

          本来能够通过訪问配置文件向cashContext中传入參数,从而推断详细的收费方法,这样当我们须要改动收费方法的时候直接改动配置文件即可了,使我们的维护更加的方便。因为这次仅仅使用了普通用户,所以计费方法仅仅有一种,仅仅採用的strStudentLevel变量传參,大大降低了系统的可维护性。所以在以后,我们做系统的时候一定要注意,尽量降低系统的耦合度,从而创造出更加优秀的产品。


  • 相关阅读:
    ASP.NET 作业题
    作业题
    作业题...
    作业题
    控件属性
    ASP控件解释
    排序
    5. 用自己的语言描述一下程序连接数据库的过程。
    4. 什么是AJAX
    3.怎样计算页面执行的时间?
  • 原文地址:https://www.cnblogs.com/mengfanrong/p/4291891.html
Copyright © 2011-2022 走看看