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

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

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

你可能感兴趣的:(策略模式)