项目重构--使用策略模式

  大家先看下下面这段代码有什么感受?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.ServiceModel;
using PCI_ClassLibrary;
using System.Windows.Threading;
using Oland.HIP.Common.Entities;
using Oland.HSS.Common;
using Oland.HIP.Common.Enums;
using System.Windows.Media.Imaging;
namespace Oland.HSS.InHospital
{
    public class BaseSwingCardWindow : BaseWindow
    {
        //检测读卡器是否打开 
        public bool IsOpened { get; set; }

        //刷卡的模块
        public Modules myModule { get; set; }

        //刷卡类型
        public CardTypeMode CardType;

        //刷卡定时器
        DispatcherTimer SwingTimer;

        //切换背景
        //public BitmapImage bgImg = new BitmapImage(new Uri("../Picture/main/yhk.png",UriKind.Relative));
        public BitmapImage bgImg;
        //切换提示信息
        public string tipMsg = "请按提示刷您的签约\n银行卡";
        public BaseSwingCardWindow() { }
        public BaseSwingCardWindow(CardTypeMode CardType)
        {
            //Load事件播放语音
            this.Loaded += new RoutedEventHandler(BaseSwingCardWindow_Loaded);
            //窗口关闭,停止定时器
            this.Closed += (object sender, EventArgs e) => { this.SwingTimer.IsEnabled = false; };

            SwingTimer = new DispatcherTimer();
            SwingTimer.Interval = TimeSpan.FromSeconds(1);
            SwingTimer.Tick += new EventHandler(SwingTimer_Tick);
            SwingTimer.IsEnabled = true;

            this.CardType = CardType;

            string strError = "";

            //硬件检测显示进度条
             Common.CommWindow.BeginProgressBar("",0);
            

            if (CardType == CardTypeMode.BankCard || CardType == CardTypeMode.MedicalCard)
            {
                if (Oland.HSS.Common.OperationPCI.CheckDevice(out strError, DeviceName.ReadCard3in1))
                {
                    IsOpened = true;
                    string error;
                    Oland.HSS.Common.OperationPCI.EnableCardIn(out error);

                    //切换为就诊卡刷卡动画
                    if (CardType == CardTypeMode.MedicalCard)
                    {
                        bgImg = new BitmapImage(new Uri("../Pictures/main/jzk.png", UriKind.Relative));
                        tipMsg = "请按提示刷您的就诊卡";
                    }
                }
                else
                {
                    IsOpened = false;
                    Common.CommWindow.EndProgressBar();
                    Common.CommWindow.ShowDialogTip("读卡器故障", strError);
                    return;
                }
            }
            else
            {
                if (HSS.Common.OperationPCI.CheckDevice(out strError, DeviceName.IDCard))
                {
                    //切换身份证背景
                    bgImg = new BitmapImage(new Uri("../Pictures/main/sfz.png", UriKind.Relative));
                    tipMsg = "请按提示刷您的身份证";
                }
                else
                {
                    IsOpened = false;
                    Common.CommWindow.EndProgressBar();
                    Common.CommWindow.ShowDialogTip("","身份证读卡器故障,请联系柜台!");
                    return;
                }
            }

            //检测小票打印机
            if (!HSS.Common.OperationPCI.CheckDevice(out strError, DeviceName.Printer))
            {
                IsOpened = false;
                Common.CommWindow.EndProgressBar();
                Common.CommWindow.ShowDialogTip("","小票打印机故障,请联系柜台!");
            }
            Common.CommWindow.EndProgressBar();
        }

        void BaseSwingCardWindow_Loaded(object sender, RoutedEventArgs e)
        {
            switch (CardType)
            {
                case CardTypeMode.IDCard:
                    HSS.Common.OperationPCI.SetVoicesUrl("Voices/请刷二代身份证.wav");
                    break;
                case CardTypeMode.MedicalCard:
                    HSS.Common.OperationPCI.SetVoicesUrl("Voices/请刷就诊卡.wav");
                    break;
                case CardTypeMode.BankCard:
                    HSS.Common.OperationPCI.SetVoicesUrl("Voices/请刷签约银行卡.wav");
                    break;
                case CardTypeMode.MedicalInsuranceCard:
                    break;
                case CardTypeMode.HealthCard:
                    break;
                default:
                    break;
            }
        }

        //定时刷新
        void SwingTimer_Tick(object sender, EventArgs e)
        {
            if (SwingCarding(CardType))
            {
                SwingTimer.IsEnabled = false;

                TransWin();
            }
        }

        //用于基类重写,实现刷卡后跳转功能
        public virtual void TransWin()
        {
        }

        /// <summary>
        /// 刷卡
        /// </summary>
        /// <param name="type">刷卡类型</param>

        public bool SwingCarding(CardTypeMode type)
        {
            string strError = null;

            CardInfo cardInfo = new CardInfo();

            switch (type)
            {
                case CardTypeMode.IDCard://刷身份证

                    IDCard_XZX_DKQ116D.IDCardData IDCardInfo = new IDCard_XZX_DKQ116D.IDCardData();
                    if (OperationPCI.ReadIDCard(ref IDCardInfo, ref strError))
                    {
                        WinContext.SetData<IDCard_XZX_DKQ116D.IDCardData>("IDCardData", IDCardInfo);
                        return true;
                    }
                    else
                    {
                        // Common.CommWindow.ShowDialogTip("错误信息", strError, true);
                    }
                    break;
                case CardTypeMode.BankCard://刷签约银行卡

                    string bdCardNo = OperationPCI.ReadMagneticCard();
                    if (bdCardNo != "")
                    {
                        cardInfo.CardNum = bdCardNo;
                        cardInfo.CardType = Oland.HIP.Common.Enums.CardTypeMode.BankCard;
                        string
                            result = GetPatientInfoAndSave(cardInfo);

                        if (result == "")
                            return true;
                        else
                        {
                            Common.CommWindow.ShowDialogTip("", result, false);
                            HSS.Common.OperationPCI.BackCard();
                            return false;
                        }
                    }
                    break;
                case CardTypeMode.MedicalCard://刷就诊卡

                    string mcCardNo = OperationPCI.ReadMagneticCard();
                    if (mcCardNo != "")
                    {
                        cardInfo.CardNum = mcCardNo;
                        cardInfo.CardType = Oland.HIP.Common.Enums.CardTypeMode.MedicalCard;

                        string result = GetPatientInfoAndSave(cardInfo);

                        if (result == "")
                            return true;
                        else
                        {
                            Common.CommWindow.ShowDialogTip("", result, false);
                            HSS.Common.OperationPCI.BackCard();
                            return false;
                        }
                    }
                    break;
                default:
                    break;
            }
            return false;
        }

        //错误信息
        static ErrorMessageInfo errInfo;

        /// <summary>
        /// 根据卡号获取病人信息并存储
        /// </summary>
        /// <param name="cardInfo">卡信息</param>
        /// <param name="isReg">是否为登记,登记从基础服务取数据,其他从住院服务取数据</param>
        /// <returns>成功返回“”</returns>
        public string GetPatientInfoAndSave(CardInfo cardInfo)
        {
            string error = "";
             Common.CommWindow.BeginProgressBar("",0);
            try
            {
                //根据卡号获取病人信息

                if (myModule == Modules.Register)
                {
                    PatientInfo patientInfo = HIPServices.BasicServiceClient.GetPatientInfoByCard(out errInfo, cardInfo);
                    if (patientInfo != null)
                    {
                        WinContext.SetData<PatientInfo>("PatientInfo", patientInfo);
                    }
                    else
                        error =cardInfo.CardType==CardTypeMode.BankCard? "非签约银行卡,请更换就银行卡重试":"非本院就诊卡,请更换后重试";
                }
                else
                {
                    InHospitalPatientInfo patientInfo = HIPServices.InHospitalServiceClient.GetHospitalPatientInfoByCard(out errInfo, cardInfo);
                    if (patientInfo != null)
                    {
                        WinContext.SetData<InHospitalPatientInfo>("InHospitalPatientInfo", patientInfo);
                    }
                    else
                    {
                        error = cardInfo.CardType == CardTypeMode.BankCard ? "非签约银行卡,请更换就银行卡重试" : "非本院就诊卡,请更换后重试";
                    }
                }
            }
            catch (Exception ex)
            {
                error = "连接服务失败,请到其它自助设备或窗口办理";
            }
            Common.CommWindow.EndProgressBar();
            return error;
        }
    }

代码凌乱,层次不清晰,过多的判断,扩展性差.....真的快看不下去了.所以决定重构下.因为最近在学设计模式,仔细分析下,这不正好策略模式很像吗?

先看下策略模式的组成:

——抽象策略角色: 策略类,通常由一个接口或者抽象类实现。

——具体策略角色:包装了相关的算法和行为。

——环境角色:持有一个策略类的引用,最终给客户端调用。

再看下策略模式的定义:

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

好,我们对策略模式稍微有了了解,那我们开始重构这段代码:

首先讲下这段代码要实现的功能,他主要是刷卡功能的实现,有就诊卡,银行卡,医保卡等,每种卡对应不同的刷卡器,同时对应不同的信息提示与背景显示等.

我们先定义一个刷卡接口,将需要改变的信息都给抽象出来.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Oland.HIP.Common.Enums;
using Oland.HIP.Common.Entities;
namespace Oland.HSS.InHospital.SwipingCard
{
    public interface ISwipingCard
    {

        /// <summary>
        /// 卡名称
        /// </summary>
         string CardName { get; }

        /// <summary>
        /// 卡类型
        /// </summary>
        CardTypeMode CardType { get; }
        /// <summary>
        /// 界面信息提示
        /// </summary>
        string TipMsg { get; }

        /// <summary>
        /// 背景图片路径
        /// </summary>
        string BackgroundImagePath { get; }

        /// <summary>
        /// 检测硬设
        /// </summary>
        /// <returns></returns>
        bool CheckDevice();

        /// <summary>
        /// 播放语音提示
        /// </summary>
        void PlayVoice();

        /// <summary>
        /// 刷卡
        /// </summary>
        /// <returns></returns>
        CardInfo SwipingCard();

        /// <summary>
        /// 将数据存储到缓存
        /// </summary>
        /// <returns></returns>
        string SaveData();
    }
}

下面分别是各个具体的刷卡类型

银行卡:

class SwipingBankCard : ISwipingCard {}

就诊卡:

class SwipingMedicalCard:ISwipingCard {

}

等等^........

下面是文件结构,如果在增加相应的类就行了

下面咱们再把最上面的代码再看下:

  public class BaseSwingCardWindow : BaseWindow
    {
        //检测读卡器是否打开 
        public bool IsOpened { get; set; }

        //刷卡的模块
        public Modules myModule { get; set; }

        //刷卡定时器
        DispatcherTimer SwingTimer;

        public BitmapImage bgImg;
        //切换提示信息
        public string tipMsg = "请按提示刷您的签约\n银行卡";
        public BaseSwingCardWindow() { }
        public BaseSwingCardWindow(ISwipingCard swipingCard)
        {
            Common.CommWindow.BeginProgressBar("", 1000);

            bgImg = new BitmapImage(new Uri(swipingCard.BackgroundImagePath, UriKind.Relative));
            tipMsg = swipingCard.TipMsg;

            //Load事件播放语音
            this.Loaded += (s, e) => swipingCard.PlayVoice();
            //窗口关闭,停止定时器
            this.Closed += (s, e) => this.SwingTimer.IsEnabled = false;

            //创建定时器间隔读取卡号
            CreateDispatcherTimer(swipingCard);

            string strError;
            //检测读卡器
            if (swipingCard.CheckDevice())
            {
                if (HSS.Common.OperationPCI.CheckDevice(out strError, DeviceName.Printer))
                {
                    IsOpened = true;
                    SwingTimer.IsEnabled = true;
                }
                else
                {
                    IsOpened = false;

                    Common.CommWindow.ShowDialogTip("", "小票打印机故障,请联系柜台!");
                }
            }
            else
            {
                IsOpened = false;
                Common.CommWindow.ShowDialogTip("", string.Format("{0}故障,请联系柜台!", swipingCard.CardName));
            }
            Common.CommWindow.EndProgressBar();
        }

        private void CreateDispatcherTimer(ISwipingCard swipingCard)
        {
            SwingTimer = new DispatcherTimer();
            SwingTimer.Interval = TimeSpan.FromSeconds(1);
            SwingTimer.Tick += (s, e) =>
            {
                CardInfo cardInfo = swipingCard.SwipingCard();
                if (!string.IsNullOrEmpty(cardInfo.CardNum))
                {
                    SwingTimer.IsEnabled = false;

                    string msg = GetPatientInfoAndSave(cardInfo);
                    if (msg != "")
                    {
                        Common.CommWindow.ShowDialogTip("", msg);
                        HSS.Common.OperationPCI.BackCard();
                    }
                    else
                    {
                        SwingTimer.IsEnabled = false;
                        TransWin();
                    }
                }
            };
        }

        //用于基类重写,实现刷卡后跳转功能
        public virtual void TransWin()
        {
        }

        //错误信息
        static ErrorMessageInfo errInfo;

        /// <summary>
        /// 根据卡号获取病人信息并存储
        /// </summary>
        /// <param name="cardInfo">卡信息</param>
        /// <param name="isReg">是否为登记,登记从基础服务取数据,其他从住院服务取数据</param>
        /// <returns>成功返回“”</returns>
        public string GetPatientInfoAndSave(CardInfo cardInfo)
        {
            //刷身份证不需要从数据库读取数据
            if (cardInfo.CardType == CardTypeMode.IDCard)
            {
                return"";
            }
            string error = "";
            Common.CommWindow.BeginProgressBar("", 0);
            try
            {
                //根据卡号获取病人信息

                if (myModule == Modules.Register)
                {
                    PatientInfo patientInfo = HIPServices.BasicServiceClient.GetPatientInfoByCard(out errInfo, cardInfo);
                    if (patientInfo != null)
                    {
                        WinContext.SetData<PatientInfo>("PatientInfo", patientInfo);
                    }
                    else
                        error = cardInfo.CardType == CardTypeMode.BankCard ? "非签约银行卡,请更换就银行卡重试" : "非本院就诊卡,请更换后重试";
                }
                else
                {
                    InHospitalPatientInfo patientInfo = HIPServices.InHospitalServiceClient.GetHospitalPatientInfoByCard(out errInfo, cardInfo);
                    if (patientInfo != null)
                    {
                        WinContext.SetData<InHospitalPatientInfo>("InHospitalPatientInfo", patientInfo);
                    }
                    else
                    {
                        error = cardInfo.CardType == CardTypeMode.BankCard ? "非签约银行卡,请更换就银行卡重试" : "非本院就诊卡,请更换后重试";
                    }
                }
            }
            catch (Exception ex)
            {
                error = "连接服务失败,请到其它自助设备或窗口办理";
            }
            Common.CommWindow.EndProgressBar();
            return error;
        }
    }

重构后代码量减少了将近一半以上,而且更容易扩展了,可读性也高了许多^,另外这里的我将接口在构造函数中使用,而更常用的方式是把ISwipingCard设为属性

怎样调用:

  SwipingCard.SwipingBankCard sbc = new SwipingCard.SwipingBankCard();
            WinQuerySwingCard winSwing = new WinQuerySwingCard(sbc);
            if (winSwing.IsOpened)
            {
                winSwing.myModule = Modules.Print;
                winSwing.Show();

                this.Close();
            }
            else
            {
                winSwing.Close();
            }

Ps:这里WinQuerySwingCard 继承自BaseSwingCardWindow

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏企鹅号快讯

Java 9 逆天的十大新特性

在介绍 Java 9 之前,我们先来看看 Java 成立到现在的所有版本。 1990 年初,最初被命名为 Oak; 1995 年 5 月 23 日,Java 语...

1905
来自专栏牛客网

19实习腾讯前端面经

我是填的部门是IEG,不过捞起我简历的是SNG。Anyway,现在到HR面了。希望一切顺利吧~ 现在来回馈牛客网啦。 腾讯 2018.03.17 一面 (内推)...

3949
来自专栏逍遥剑客的游戏开发

Nebula3 in CLR

1133
来自专栏张善友的专栏

TransactionScope和Enterprise Libray 3.0 Data Access Application Block

Enterprise Libray 3.0已经发布了,具体可参见TerryLee的 Enterprise Library 3.0 发布.下载了看看,有非常激动人...

1808
来自专栏流媒体人生

SetTimer在无窗口和有窗口线程的使用

 今天犯了一个粗心的错误,在无窗口线程中,SetTimer中设置计时器ID,而WM_TIMER消息响应函数中得到的计时器ID却不是之前设置的计时器ID.

612
来自专栏向治洪

IOS入门之StoryBoard

概述 在iOS的发展历程中,IOS开发经历了三种主要流派:使用代码手写UI及布局;使用单个xib文件组织viewController或者view;使用Story...

1797
来自专栏潇涧技术专栏

Lint Tool Analysis (3)

本系列的几篇源码分析文档意义不大,如果你正好也在研究lint源码,或者你想知道前面自定义lint规则中提出的那几个问题,抑或你只是想大致了解下lint的源码都有...

431
来自专栏bboysoul

关于linux下raid的设备文件和格式化

今天给dell t20装了zstack,没错zstack镜像底层其实就是centos,服务器里面有四块硬盘,一块300g的我是做系统盘的,三块1T的硬盘我是打算...

682
来自专栏互联网杂技

react+redux+webpack教程3

现代web页面里到处都是ajax,所以处理好异步的代码非常重要。 这次我重新选了个最适合展示异步处理的应用场景——搜索新闻列表。由于有现成的接口,我们就不用自己...

35810
来自专栏数据之美

修改 mysql/oracle/bash/vimrc/cmd 提示符格式与颜色

(1)修改mysql提示符: MySQL 客户端的默认提示符是 "mysql>",基本上没什么实际作用。其实可以修改这个提示符,让它显示一些有用的信息,例如当前...

19510

扫描关注云+社区