【机房重构】——观察者模式解决三种下机

简介: 【机房重构】——观察者模式解决三种下机

引言


对于重构来说我们知道在机房收费这个系统中有三种下机——正常下机、强制所有下机、选择强制下机。在第一遍的时候我们就是在做完正常下机以后,然后复制代码来完成,在重构的时候有了设计模式作为基础,我们可以用观察者模式轻松搞定这三种下机。


基础篇


基本概念:观察者模式又叫做发布-订阅模式,它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化的时,会通知所有的观察者对象,是他们能够自动更新自己。


基本类图:


20150125231721828.jpg


应用场景:当一个对象的改变需要同时改变其他对象,并且他不知道具体有多少对象有待改变时,应该考虑使用观察者模式。总的来讲,观察者模式所做的工作其实就是子啊解除耦合,让耦合的双方都依赖于抽象而不是依赖于具体,从而是得各自的变化都不会影响另一边的变化!


实战篇


在上面介绍了关于观察者模式的一些基本知识,现在就借助机房重构这个机会小试一把。因为我在下机的过程中需要进行如下判断:卡号是否存在、卡号是否正在上机、是否插入上机记录表等。这些都是每个下机都要判断的,所以用观察者模式来解决这个问题。

类图如下:

20150125234744586.jpg

部分代码如下:

'**********************************************
'说明:在下机的时候用观察者模式,抽象观察者
'命名空间:BLL
'机器名称:晓
'创建日期:2015/1/4 22:50:10
'作者:郑浩
'版本号:V1.00
'**********************************************
Public MustInherit Class SubjetBll
    Private ilist As IList(Of ObserverBLL) = New List(Of ObserverBLL)
    ''' <summary>  
    ''' 添加观察者  
    ''' </summary>  
    ''' <param name="observer">抽象观察者类</param>  
    Public MustOverride Sub Attach(ByVal observer As ObserverBLL)
    ''' <summary>  
    ''' 去除观察者  
    ''' </summary>  
    ''' <param name="observer">抽象观察者类</param>  
    Public MustOverride Sub Detach(ByVal observer As ObserverBLL)
    ''' <summary>  
    ''' 通知观察者  
    ''' </summary>  
    Public MustOverride Sub Notify(ByVal online As Entity.EN_CardInfo)
End Class
'**********************************************
'说明:抽象的观察者
'命名空间:BLL
'机器名称:晓
'创建日期:2015/1/4 22:53:55
'作者:郑浩
'版本号:V1.00
'**********************************************
Public MustInherit Class ObserverBLL
    '定义一个抽象的更新的方法
    Public MustOverride Sub Update(ByVal online As Entity.EN_CardInfo)
End Class
说明:上机的第一步检查卡号时候存在
'命名空间:BLL
'机器名称:晓
'创建日期:2015/1/3 8:20:17
'作者:郑浩
'版本号:V1.00
'**********************************************
Imports IDAL
Imports BLL.OnLineStateBLL
Public Class IsExitCardNoBLL : Inherits OnLineStateBLL
    Public Overrides Sub online(ByVal cardinfo As Entity.EN_CardInfo, ByVal upline As BLL.UpLineBLL)
        Dim factory As New DAL.Factory
        Dim Ionline As IOnOffLine
        Ionline = factory.CreateOnOffLine
        Dim dt As DataTable
        dt = Ionline.CheckCardInfo(cardinfo)
        '判断卡号是否存在
        If (dt.Rows.Count = 0) Then
            MsgBox("卡号不存在")
        Else
            cardinfo.StudentName = dt.Rows(0).Item(3)
            cardinfo.Status = "正常上机"
            upline.SetNextState(New BalanceStateBLL)
            upline.CardOnLine(cardinfo)
        End If
    End Sub
End Class
'**********************************************
'说明:插入上机记录
'命名空间:BLL
'机器名称:晓
'创建日期:2015/1/5 23:45:31
'作者:郑浩
'版本号:V1.00
'**********************************************
Imports BLL.ObserverBLL
Imports IDAL
Public Class OInsertOnLineRecord : Inherits BLL.ObserverBLL
    Public Overrides Sub Update(online As Entity.EN_CardInfo)
        If Entity.PublicVariables.observeflag = "用户未上机" Then
        Else
            '首先在上机表中读取数据,然后赋给实体
            Dim factory As New DAL.Factory
            Dim Ionlining As IOnLining
            Ionlining = factory.CreateOnLining
            Dim dt As DataTable
            dt = Ionlining.IsCardNoLining(online)
            '计算消费时间
            Dim offdate As Date  '下机日期
            offdate = Date.Today()
            Dim offtime As String '下机时间
            offtime = Date.Now.ToString("hh:mm:ss")
            Dim spenttime As Double    '消费的时间
            Dim realitytime As Double    '实际消费时间
            Dim spentmoney As Integer    '消费金额
            Dim type As String          '用户类型
            Dim cardbalance As Integer
            '调用获得基本数据方法来获得基本数据
            Dim basicdatafactory As New DAL.Factory
            Dim Ibasicdata As ISetBasicData
            Ibasicdata = basicdatafactory.CreateBasicData
            Dim table As DataTable
            table = Ibasicdata.GetBasicData()
            '计算实际消费时间
            realitytime = 0
            spenttime = DateDiff(DateInterval.Minute, dt.Rows(0).Item(3), offdate) + DateDiff(DateInterval.Minute, CDate(dt.Rows(0).Item(4)), CDate(offtime))
            '判断消费时间和准备时间的大小
            If (spenttime < table.Rows(0).Item(5)) Then
                realitytime = 0
            ElseIf (spenttime < table.Rows(0).Item(4)) Then
                realitytime = table.Rows(0).Item(4)
            Else
                realitytime = spenttime
            End If
            '调用检查卡号的方法,来获取用户类型和余额
            Dim cardfactory As New DAL.Factory
            Dim Ionline As IOnOffLine
            Ionline = cardfactory.CreateOnOffLine
            Dim carddt As DataTable
            carddt = Ionline.CheckCardInfo(online)
            type = carddt.Rows(0).Item(15)     '获得用户类型
            cardbalance = carddt.Rows(0).Item(8)  '获得卡内余额
            Dim basicdata As New Entity.EN_BasicData
            basicdata.FixPrice = table.Rows(0).Item(1)
            basicdata.TempPrice = table.Rows(0).Item(2)
            '调用CashFactory 来计算消费金额
            Dim cashfactory As BLL.CashFactory = New CashFactory()
            Dim csuper As BLL.CashSuper
            csuper = cashfactory.CreateCashAccept(type)
            spentmoney = csuper.AcceptCash(basicdata, realitytime)
            '定义一个实体用来插入上机记录
            Dim onlinerecord As New Entity.EN_CardInfo
            onlinerecord.CardNo = dt.Rows(0).Item(1)
            onlinerecord.StudentName = dt.Rows(0).Item(2)
            onlinerecord.OnDate = dt.Rows(0).Item(3)
            onlinerecord.OnTime = dt.Rows(0).Item(4)
            onlinerecord.OffDate = offdate
            onlinerecord.OffTime = offtime
            onlinerecord.ConsumeTime = spenttime
            onlinerecord.ConsumeMoney = spentmoney
            onlinerecord.Balance = cardbalance - spentmoney
            onlinerecord.WorkerComputer = System.Net.Dns.GetHostName().ToString()
            onlinerecord.Status = online.Status
            onlinerecord.Type = type
            onlinerecord.UserName = Entity.PublicVariables._username
            '用于传给U层显示在文本框中
            Entity.PublicVariables.onlinerecordinfo = onlinerecord
            '调取学生表中的信息,用于填写U层的学生的基本信息
            Dim Cfactory As New DAL.Factory
            Dim CIonline As IOnOffLine
            CIonline = factory.CreateOnOffLine
            Dim Cdt As DataTable
            Cdt = Ionline.CheckCardInfo(online)
            '获得学生的基本信息后,赋给全局变量,然后传递给U层
            Entity.PublicVariables.StudentBasicInfo = Cdt
            '更新上机记录表中的数据
            Dim Ionlinerecord As IOnOffLine
            Dim result As Integer
            Ionlinerecord = factory.CreateOnOffLine
            result = Ionlinerecord.UpdateLineRecord(onlinerecord)
            If result = 0 Then
                MsgBox("更新上机记录失败")
            End If
        End If
    End Sub
End Class
<pre name="code" class="vb">**********************************************
'说明:具体的观察者
'命名空间:Facade
'机器名称:晓
'创建日期:2015/1/6 0:23:04
'作者:郑浩
'版本号:V1.00
'**********************************************
Public Class FacadeFormalOnLine
    ''' <summary>
    ''' 正常上机
    ''' </summary>
    ''' <param name="online"></param>
    ''' <remarks></remarks>
    Public Sub FormalOnLine(ByVal online As Entity.EN_CardInfo)
        Dim Fformalonline As New BLL.NormalOffLine
        Fformalonline.Attach(New BLL.OCardIsExist)
        Fformalonline.Attach(New BLL.OCardIsOnLine)
        Fformalonline.Attach(New BLL.OInsertOnLineRecord)
        Fformalonline.Notify(online)
    End Sub
End Class

思考


我们都已经做过了一遍机房收费系统,我们根据需求会发现这样一个问题,当我们判断到卡号不存在时,会给出一个提醒“卡号不存在”,这时候后面的判断就不用进行了,直接退出,但是在观察这模式会自动遍历这些观察者,这就造成重复提示的缺陷,为了避免这个缺陷,我在实体层定义了一个全局变量用来在B层控制是否进行下一个判断。虽然达到做了目的,但是总感觉这样的办法不是最好的,这个问题正在研究中,如果哪位大神有好的想法,请留言提示!


小结


其实下机和上机时计算消费的判断思路差不多,但是为了更好的联系设计模式的知识,所以采用了不同的模式,在上机计算消费时采用了状态模式,详见【机房重构】——策略模式+简单工厂计算消费,在重构的时候主要是对前面学习的这些编程的思想和知识的一个灵活运用,所以在做的时候尽可能的采用不同思路和想法从多个方面来完成相应的功能,在这个阶段的运用没有对错之分,只有用过以后才能在下一次编程的时候更加灵活的运用它,所有希望同学能打开思路进行机房重构,Come On!!1

目录
相关文章
|
3天前
|
弹性计算 运维 搜索推荐
三翼鸟携手阿里云ECS g9i:智慧家庭场景的效能革命与未来生活新范式
三翼鸟是海尔智家旗下全球首个智慧家庭场景品牌,致力于提供覆盖衣、食、住、娱的一站式全场景解决方案。截至2025年,服务近1亿家庭,连接设备超5000万台。面对高并发、低延迟与稳定性挑战,全面升级为阿里云ECS g9i实例,实现连接能力提升40%、故障率下降90%、响应速度提升至120ms以内,成本降低20%,推动智慧家庭体验全面跃迁。
|
4天前
|
数据采集 人工智能 自然语言处理
3分钟采集134篇AI文章!深度解析如何通过云无影AgentBay实现25倍并发 + LlamaIndex智能推荐
结合阿里云无影 AgentBay 云端并发采集与 LlamaIndex 智能分析,3分钟高效抓取134篇 AI Agent 文章,实现 AI 推荐、智能问答与知识沉淀,打造从数据获取到价值提炼的完整闭环。
372 91
|
5天前
|
域名解析 人工智能
【实操攻略】手把手教学,免费领取.CN域名
即日起至2025年12月31日,购买万小智AI建站或云·企业官网,每单可免费领1个.CN域名首年!跟我了解领取攻略吧~
|
5天前
|
SQL 人工智能 自然语言处理
Geo优化SOP标准化:于磊老师的“人性化Geo”体系如何助力企业获客提效46%
随着生成式AI的普及,Geo优化(Generative Engine Optimization)已成为企业获客的新战场。然而,缺乏标准化流程(Geo优化sop)导致优化效果参差不齐。本文将深入探讨Geo专家于磊老师提出的“人性化Geo”优化体系,并展示Geo优化sop标准化如何帮助企业实现获客效率提升46%的惊人效果,为企业在AI时代构建稳定的流量护城河。
385 156
Geo优化SOP标准化:于磊老师的“人性化Geo”体系如何助力企业获客提效46%
|
4天前
|
数据采集 缓存 数据可视化
Android 无侵入式数据采集:从手动埋点到字节码插桩的演进之路
本文深入探讨Android无侵入式埋点技术,通过AOP与字节码插桩(如ASM)实现数据采集自动化,彻底解耦业务代码与埋点逻辑。涵盖页面浏览、点击事件自动追踪及注解驱动的半自动化方案,提升数据质量与研发效率,助力团队迈向高效、稳定的智能化埋点体系。(238字)
267 156
|
12天前
|
机器人 API 调度
基于 DMS Dify+Notebook+Airflow 实现 Agent 的一站式开发
本文提出“DMS Dify + Notebook + Airflow”三位一体架构,解决 Dify 在代码执行与定时调度上的局限。通过 Notebook 扩展 Python 环境,Airflow实现任务调度,构建可扩展、可运维的企业级智能 Agent 系统,提升大模型应用的工程化能力。