zoukankan      html  css  js  c++  java
  • 机房收费系统之状态模式

      这次合作机房收费系统时,经过思考,在上下机那儿觉得既可以用状态模式还可以用观察者模式模式。

      观察者模式:(有时又被称为发布-订阅模式、模型-视图模式、源-收听者模式或从属者模式)他定义一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。

    UML图:

      抽象被观察者提供一个借口让观察者进行添加和删除观察者。

        添加(Attach):新增观察者,一追踪目标对象的变化。

        删除(Detach):将已有的观察者删除。

        通知(Notify):利用观察者提供的更新函数来通知此目标已经产生变化。

      抽象观察者有一个虚拟的更新(Update)方法,每天具体的观察者要实现自己的更新方法。当目标对象改变时,会呼叫自己的通知函数来通知给每一个观察者,观察者实现自己的更新方法。


      机房合作时上机、下机和强制下机可以用观察者模式。上机、下机和强制下机时具体的被观察者,判断卡是否存在,卡余额是否足够,卡是否正在上机等都是具体的观察者。这里为了练习,上机我用了宁外一个模式。下机、强制下机用观察者模式的UML图:

      具体被观察者下机类的代码:

      

    '观察者列表
        ''Private ilist As IList(Of ObserverBLL)
        Private ilist As IList(Of ObserverBLL) = New List(Of ObserverBLL)
    
        ''' <summary>
        ''' 添加观察者
        ''' </summary>
        ''' <param name="observer">抽象观察者类</param>
        Public Overrides Sub Attach(ByVal observer As ObserverBLL)
            ilist.Add(observer)
        End Sub
    
        ''' <summary>
        ''' 去除观察者
        ''' </summary>
        ''' <param name="observer">抽象观察者类</param>
        Public Overrides Sub Detach(ByVal observer As ObserverBLL)
            ilist.Remove(observer)
        End Sub
    
        ''' <summary>
        ''' 通知观察者
        ''' </summary>
        Public Overrides Sub Notify(ByVal encard As cardentity)
            For Each observer As ObserverBLL In ilist
                observer.Update(encard)
            Next
    
        End Sub

      具体观察者代码:

      卡是否存在:

    ''' <summary>
        ''' 更新,查看卡是否存在
        ''' </summary>
        ''' <param name="enCard">卡号</param>
        Public Overrides Sub Update(ByVal enCard As CardEntity)
            Dim dataAccess As Factory.FactoryReflex                     '定义一个工厂对象
            dataAccess = Factory.FactoryReflex.GetInstance()            '实例化工厂对象
    
            Dim icard As ICard                                          '定义一个接口
            icard = dataAccess.CreateICard()                            '创建接口
            Dim dtCard As New DataTable                                 '定义一个datatable对象
            dtCard = icard.SelectCardUse(enCard)                      '调用D层中查询卡的方法
            '判断该卡是否存在
            If dtCard.Rows.Count = 0 Then
                Throw New Exception("该卡不存在!")
            End If
        End Sub


      是否正在上机:

    ''' <summary>
        ''' (卡号),将enCard实体的卡号赋值个他
        ''' </summary>
        Private enLineRecord As New LineRecordEntity
    
        ''' <summary>
        ''' 更新,查询该卡是否正在上机
        ''' </summary>
        ''' <param name="enCard">卡号</param>
        Public Overrides Sub Update(ByVal enCard As CardEntity)
            Dim dataAccess As Factory.FactoryReflex                     '定义一个工厂对象
            dataAccess = Factory.FactoryReflex.GetInstance()            '实例化工厂对象
    
            Dim ilineRecord As ILineRecord                              '定义一个接口
            ilineRecord = dataAccess.CreateILine()                      '创建接口
            Dim dtLineRecord As New DataTable
            'Dim enLineRecord As New LineRecordEntity
            enLineRecord.ProCardId = enCard.ProCardId
            dtLineRecord = ilineRecord.SelectIsOnLine(enLineRecord)                   '查询该卡是否正在上机
            '判断该卡是否正在上机
            If dtLineRecord.Rows.Count = 0 Then
                Throw New Exception("该卡没有上机!")
            End If
        End Sub

      更新上机记录: 

    ''' <summary>
        ''' 更新,将上机记录更新到表T_LineRecord
        ''' </summary>
        ''' <param name="enCard">卡号</param>
        Public Overrides Sub Update(ByVal enCard As CardEntity)
            Dim dataAccess As Factory.FactoryReflex                     '定义一个工厂对象
            dataAccess = Factory.FactoryReflex.GetInstance()            '实例化工厂对象
    
            Dim ilineRecord As ILineRecord                              '定义一个接口
            ilineRecord = dataAccess.CreateILine()                      '创建接口
            Dim dtLineRecord As New DataTable
            enLineRecord.ProCardId = enCard.ProCardId
            dtLineRecord = ilineRecord.SelectIsOnLine(enLineRecord)     '查询上机记录
    
            Dim offDate As Date = CDate(Format(Now(), "yyyy/M/d"))       '下机日期
            Dim offTime As String = Format(Now(), "HH:mm")             '下机时间
            Dim spentTime As Integer
            spentTime = CInt(DateDiff(DateInterval.Minute, CDate(dtLineRecord.Rows(0).Item("上机时间").ToString), CDate(offTime)))
    
            '读取用户类型
            Dim type As String                                         '存放用户类型
            Dim icard As ICard                                          '定义一个接口
            icard = dataAccess.CreateICard()                            '创建接口
            Dim dtCard As New DataTable                                 '定义一个datatable对象
            dtCard = icard.SelectCardUse(enCard)                      '调用D层中查询卡的方法
            type = dtCard.Rows(0).Item("卡类型").ToString             '用户类型
    
            '调用计算上机消费的方法
    
            Dim cashContext As New CashContextBLL(spentTime, type)
            cashContext.ProStrTime = spentTime
            cashContext.ProType = type
            spentCash = cashContext.GetResult()
            leaveCash = CSng(dtCard.Rows(0).Item("卡内余额").ToString) - spentCash
    
            '给上机记录实体赋值
            enLineRecord.ProOffDate = offDate
            enLineRecord.ProOffTime = offTime
            enLineRecord.ProConsumeTime = spentTime
            enLineRecord.ProConsumeCash = spentCash
            enLineRecord.ProOnDate = CDate(dtLineRecord.Rows(0).Item("上机日期").ToString)
            enLineRecord.ProOnTime = dtLineRecord.Rows(0).Item("上机时间").ToString
            enLineRecord.ProLeaveCash = leaveCash
    
            '将记录更新到数据库上机记录表里
            Dim bln As Boolean
            bln = ilineRecord.UpdateOnLine(enLineRecord)
        End Sub

      更新卡余额:

    ''' <summary>
        ''' 更新,更新卡的余额,余额从类ModifyLineRecordBLL中读取
        ''' </summary>
        ''' <param name="enCard">卡号</param>
        Public Overrides Sub Update(ByVal enCard As CardEntity)
            Dim dataAccess As Factory.FactoryReflex                     '定义一个工厂对象
            dataAccess = Factory.FactoryReflex.GetInstance()            '实例化工厂对象
    
            Dim icard As ICard                                          '定义一个接口
            icard = dataAccess.CreateICard()                            '创建接口
            Dim bln As Boolean
            enCard.ProCash = ModifyLineRecordBLL.leaveCash
            bln = icard.UpdateCardCash(enCard)
    
        End Sub

      在计算上机消费时加上了策略模式,这里就不介绍了。


  • 相关阅读:
    原型设计作业
    20210405-1 案例分析作业
    要命的作业
    20210309-1 准备工作
    20210309-2 阅读任务
    前端用js获取本地文件的内容
    2019春第四周作业
    解决BootStap TreeView插件在 BootStrap4上不兼容问题
    ABP VNEXT使用PUT方法时报”对象已被修改,乐观并发失败“解决方案
    【一步一步入坑ABP VNEXT】安装ABP CLI
  • 原文地址:https://www.cnblogs.com/javawebsoa/p/3086062.html
Copyright © 2011-2022 走看看