zoukankan      html  css  js  c++  java
  • 项目重构--使用策略模式

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

    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 = "请按提示刷您的签约
    银行卡";
            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 = "请按提示刷您的签约
    银行卡";
            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
  • 相关阅读:
    angularJS指令--在各自的控制器里调用不同的函数
    npm install时的一个小问题
    按特定形式生成当前日期的函数
    js判断对象是否是数组的方法
    转正考试的几个考点
    JS 对象转化为数组
    requireJS随笔
    使用bootstrap-select插件,赋初始值
    理解Stream(一)——串行与终止操作
    python requests 库 首次使用
  • 原文地址:https://www.cnblogs.com/smiler/p/3293369.html
Copyright © 2011-2022 走看看