职责链模式——机房收费系统下机结账

在机房收费系统中,学生下机结账最让人头疼了。因为学生的消费时间(下机时间-上机时间-上机准备时间)有三种情况:

1.消费时间<=0,也就是下机时间与上机时间的间隔在上机准备时间范围内,这种情况是不收费的。

2.消费时间<=最少上机时间,这种情况下消费时间按照最少上机时间收费。

3.消费时间>最少上机时间,这种情况还要考虑递增单位时间。比如递增单位时间是10分钟,消费时间是42分

钟,42/10=4.....2,这种情况要按照50分钟收费。

以上消费时间就分了三种情况,更复杂的是第二种和第三种情况还需要分别考虑用户类型是固定用户还是临时用

户,这两种用户类型的费率不一样。在前两次的机房收费系统中,鄙人花费了大量的时间和精力,整出大量的、嵌套

的if语句来计算消费。if语句用多了,程序就有坏味道了。既然学习了设计模式,就要运用到实践中。

职责链模式的定义是:使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系。将这个

对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。在机房收费系统下机结账中,“请求”中

携带着用户消费时间和用户类型,“处理”就是三种不同消费时间下的不同计费方式。请求在这三种处理中传递,

消费时间符合哪种处理,就到哪种处理方法中计费。下面展示类图和具体的代码:

Request:

<span style="font-family:Microsoft YaHei;font-size:18px;">Public Class Request
        ''' <summary>
        ''' 卡类型
        ''' </summary>
        Private cardType As String
        ''' <summary>
        ''' 消费时间,单位分
        ''' </summary>
        Private consumeTime As Integer
        ''' <summary>
        ''' 卡类型
        ''' </summary>
        Public Property ProcardType() As String
            Get
                Return cardType
            End Get
            Set(ByVal Value As String)
                cardType = Value
            End Set
        End Property
        ''' <summary>
        ''' 消费时间,单位分
        ''' </summary>
        Public Property ProconsumeTime() As Integer
            Get
                Return consumeTime
            End Get
            Set(ByVal Value As Integer)
                consumeTime = Value
            End Set
        End Property
    End Class ' Request</span>

ChargeMethod:

<span style="font-family:Microsoft YaHei;font-size:18px;">''' <summary>
	''' 抽象类,计费方法
	''' </summary>
    Public MustInherit Class ChargeMethod
        ''' <summary>
        ''' 上级
        ''' </summary>
        Protected superior As ChargeMethod
        Public MustOverride Sub SetSuperior(ByVal superior As ChargeMethod)
        ''' <summary>
        ''' 虚方法,子类重写
        ''' </summary>
        ''' <param name="request"></param>
        Public MustOverride Function RequestApplication(ByVal request As Request) As Decimal

    End Class ' ChargeMethod</span>

ChargeMethodA:

<span style="font-family:Microsoft YaHei;font-size:18px;">''' <summary>
    ''' 没有消费时间的方法
	''' </summary>
    Public Class ChargeMethodA : Inherits Pack.BLL.ChargeMethod
        ''' <summary>
        ''' 计费方式一:在准备上机时间范围内不收钱,消费为0
        ''' </summary>
        ''' <param name="request"></param>
        Public Overrides Function RequestApplication(ByVal request As Request) As Decimal
            If (request.ProconsumeTime <= 0) Then
                Return 0
            Else
                Return Me.superior.RequestApplication(request)
            End If
        End Function
        Public Overrides Sub SetSuperior(ByVal superior As ChargeMethod)
            Me.superior = superior
        End Sub
    End Class ' ChargeMethodA</span>

ChargeMethodB:

<span style="font-family:Microsoft YaHei;font-size:18px;">''' <summary>
	''' 消费时间不超过最少上机时间
	''' </summary>
    Public Class ChargeMethodB : Inherits Pack.BLL.ChargeMethod
        ''' <summary>
        ''' 计费方式二:消费时间小于至少上机时间,按照至少上机时间计费
        ''' </summary>
        ''' <param name="request"></param>
        Public Overrides Function RequestApplication(ByVal request As Request) As Decimal
            If (request.ProcardType = "固定用户" And request.ProconsumeTime <= leastTime) Then
                Return rate * leastTime / 60
            ElseIf (request.ProcardType = "临时用户" And request.ProconsumeTime <= leastTime) Then
                Return tmpRate * leastTime / 60
            Else
                Return Me.superior.RequestApplication(request)
            End If
        End Function
        Public Overrides Sub SetSuperior(ByVal superior As ChargeMethod)
            Me.superior = superior
        End Sub
    End Class ' ChargeMethodB</span>

ChargeMethodC:

<span style="font-family:Microsoft YaHei;font-size:18px;"> ''' <summary>
        ''' 计费方式三:消费时间大于至少上机时间的计费方法
        ''' </summary>
        ''' <param name="request"></param>
        Public Overrides Function RequestApplication(ByVal request As Request) As Decimal
            Dim unitCount As Integer '消费时间中含有递增单位时间的个数
            If (consumeTime / unitTime = 0) Then
                unitCount = consumeTime / unitTime
            Else
                unitCount = Fix(consumeTime / unitTime) + 1
            End If

            If (request.ProcardType = "固定用户" And request.ProconsumeTime > leastTime) Then
                Return rate * unitCount * unitTime / 60
            ElseIf (request.ProcardType = "临时用户" And request.ProconsumeTime > leastTime) Then
                Return tmpRate * unitCount * unitTime / 60
            End If
        End Function
        Public Overrides Sub SetSuperior(ByVal superior As ChargeMethod)
            Me.superior = superior
        End Sub
    End Class ' ChargeMethodC</span>

具体使用的时候,代码如下:

<span style="font-family:Microsoft YaHei;font-size:18px;">Dim a As New Pack.BLL.ChargeMethodA
        Dim b As New Pack.BLL.ChargeMethodB
        Dim c As New Pack.BLL.ChargeMethodC

        Dim request As New Pack.BLL.Request
        Dim consumeCash As Decimal '消费金额

        '设置链的传递方式,方式1→方式2→方式3
        a.SetSuperior(b)
        b.SetSuperior(c)

        request.ProcardType = "临时用户"
        request.ProconsumeTime = 42  '单位:分钟
        consumeCash = a.RequestApplication(request)</span>

这样做虽然创造了好多个类,但把if都封装了,对待所有的学生都一视同仁,不必考虑他属于哪种处理情况,复杂

的计费过程交给程序自己默默地判断、计算。使用职责链模式最重要的有两点:一个是事先给每个具体处理设置它

的"后继者",也就是链传递的下一个对象。另一个是在每个具体处理中对请求做出判断,是可以处理呢,还是转移到

它的后继者。本例中用户类型就两种,如果三种、四种......呢?这个时候可以引入策略模式和简单工厂。通过这次大胆

尝试职责链模式的应用,深刻体会到实践的重要性。

时间: 2024-10-25 19:37:20

职责链模式——机房收费系统下机结账的相关文章

机房收费系统 之 结账漏洞

声明:以下内容只对将卡表和退卡表放在同一张表的同学适用! 最近大家都已经开始做VB.NET机房收费系统重构版,在这里跟大家聊聊我在机房收费系统中发现的漏洞. 在机房收费系统中有这样一个窗体--结账.个人认为结账的功能是:领导对操作员注册退卡进行结账,简单的说就是领导来收钱,如果你是一个操作员,每天充值退卡,你要知道你这段时间都赚了多少钱. 今天要说的重点就是卡表的结账!在结账中,有一个购卡,有一个退卡.也就是说,对于同一张卡,它注册后需要结账一次,退卡后也需要结账一次. 让我们来看看我数据库的卡

职责链模式+策略模式+反射+配置文件,完美实现下机操作(一)

纵观机房收费系统,逻辑最复杂的也就是下机操作了,这几天一直在考虑下机操作该如何进行. 流程分析: 判断卡号是否存在与是否上机 上机时间的处理 根据时间计算消费金额 更新余额,添加记录 关于逻辑的操作主要集中在两个计算上面时间和金额.首先说上机时间的处理问题,做之前我看了下第一版机房收费系统关于下机的操作: '计算消费时间 TxtTime.Text =DateDiff("n", Trim(TxtOntime.Text), Trim(Offtime)) TxtTime.Text = Txt

机房收费系统之下机完整版

前篇博客只是简单的说了下,机房收费系统下机的简单思路,下面来正式的介绍下整个流程. 分析 由于下机的时候需要涉及到两个表中的数值--StudentInfo表和OnlineInfo表,那么我们的思路就是如何能够简化查 询的操作. 学生表中包含的学生的静态信息,而上机信息表中则包含了有关学生上机的所有的信息. 流程 1.更新学生下机信息 2.触发器触发后,会自动的更新学生的消费时间,消费金额并更新学生余额 3.两张表联合查询有关界面上的所有信息 4.为所有的文本框赋值 注意:其实最有意思的就是触发器

机房收费系统——报表(2)

二.代码部分 跟之前写的excel相比,我觉得报表还是有点相同的.大体思路是这样的: 先定义. (报表:Dim Withevents 对象变量 As 类名 这种用法是加载该类的事件,Withevents之后就能在代码编辑窗看到该类的事件了(如果有的话). 因为类不像控件,双击控件就可以进入事件编辑. 使用WithEvents 变量时,应该注意下面这些限制条件: WithEvents变量不能是派生对象变量.也就是说,不能把它声明为As  Object-当声明该变量时必须指定类名. 不能把 With

设计模式@第26章:职责链模式

第26章:职责链模式 一.学校 OA 系统的采购审批项目:需求是 采购员采购教学器材 如果金额 小于等于 5000, 由教学主任审批 (0<=x<=5000) 如果金额 小于等于 10000, 由院长审批 (5000<x<=10000) 如果金额 小于等于 30000, 由副校长审批 (10000<x<=30000) 如果金额 超过 30000 以上,有校长审批 ( 30000<x) 请设计程序完成采购审批项目 二.传统方案解决OA 系统审批,传统的设计方案(类图

图解Java设计模式之职责链模式

图解Java设计模式之职责链模式 学校OA系统的采购审批项目 :需求是 传统方案解决OA系统审批,传统的设计方案 职责链模式基本介绍 职责链模式解决OA系统采购审批 职责链模式在SpringMVC框架应用的源码 职责链模式的注意事项和细节 学校OA系统的采购审批项目 :需求是 采购员采购教学器材1)如果金额 小于等于 5000,由教学主任审批 (0<=x<=5000)2)如果金额 小于等于 10000,由院长审批(5000 < x <= 10000)3)如果金额 小于等于 3000

机房收费系统学生下机结账小结

这几天一直在考虑机房收费系统学生下机操作.学生下机,一则须要加入学生下机记录信息:还须要计算学生在整 个上机过程中所花费的金额,而且更新学生剩余金额.那么如何做在性能上或者扩展上更好一些呢? 操作 1.加入学生下机信息 2.计算学生上机时间 3.依据上机时间来计算学生所花费的金额 4.更新学生的剩余金额 设计模式 在通过学生上机时间来计算学生所花费的金额这步操作上,须要进行一些条件分支语句的推断.由于上机时间被分为 了三部分:准备时间.至少上机时间.上机时间.所以在步骤3中有大量的条件分支语句,

职责链模式应用——下机(机房重构知识点总结)

下机涉及两个方面,消费时间和消费金额. 对消费时间的处理用的是职责链模式,感觉这个模式用的非常妙,參考的师哥的博客:<机房收费下机中用到的策略与职责链解析>:消费金额的处理用策略模式.针对不同的用户类型. 这里着重介绍职责链的应用. 依据需求,将时间分为三个阶段,准备时间:不收取费用:至少上机时间:大于准备时间,小于至少上机时间的,一律按至少上机时间算.单位递增时间:大于至少上机时间后.按单位递增时间累加. TimeHandler类,定义一个处理请示的接口 Public MustInherit

有关机房收费系统学生下机的思考

?? 所谓的专家,就是在一个非常小的领域把全部的错误都犯过的人 ---------题记 做机房收费系统也有一段时间了,眼下已经进行到学生下机操作了. 由于学生下机操作时.须要依据不同用户的类别.来进行对应的结账服务.于是乎就想到了曾经学习到的设计模式,那么针对这个问题.能够用到那些模式呢?小编在这里总结一下.(可能有些模式过于勉强,但这都无所谓,学习的真谛就在于此,不断的反复和实验) --------------------------------------------------------