订餐系统总结(三)策略模式应用于处罚方案管理


   需求介绍:

某学校实现网上订餐后,到食堂刷卡就餐。可是为了督促大家要先在网上订餐后再去食堂就餐(食堂可以实现按实际所需做饭),对于未订餐的要进行处罚;还有一种情况是订餐未就餐的情况;当然最后是正常就餐(也就是订餐后就餐)。学校希望对于前两种情况进行相应的处罚,比如说:三天不允许订餐,当然也就不允许就餐、或者是罚款、再或者是先警告指定次数,无效后再进行处罚(也就是罚款或者几天不允许订餐)。

说实话这个需求着实让我头疼了好几天啊!我们拿到这个需求后,第一印象也许就是要用策略模式进行处理,可是当时我又这样想,对于这两种处罚情况(订餐未就餐,未订餐就餐),要执行不同的操作啊!比如说对于现金处罚来说吧:如果是对于订餐未就餐的情况,那么应该把这些未处理的订单的状态改为处理,而未订餐就餐因为没有订单就不用执行这个操作。

         也就是因为这样想,对于每一种处罚类型,它的实现也是不一样的,所以当时犹豫了一下,想用抽象工厂模式来解决这个问题。可是抽象工厂是用来解决多个抽象产品的问题,对于多个抽象产品的实现存在不小的差异,而且两种产品不是经常变化的。如果真的用抽象工厂来解决这个问题的话,那么将会产生大量的重复代码,那是很糟糕的。

那么我们再来看看策略模式。  

策略模式定义了算法家族,分别封装起来,让它们之间可以相互替换,此模式让算法的变化,不会影响到使用算法的客户。

策略模式是用来封装算法的,但在实践中,我们发现可以用它来封装几乎任何类型的规则,只要在分析过程中听到需要在不同时间应用不同的业务规则,就可以考虑使用策略模式处理这种变化的可能性。

经过仔细地分析,我们不难发现,这里运用策略模式来解决是比较合理的,那么,对于这两种情况(订餐未就餐处罚、未订餐就餐处罚),怎么进行代码的复用呢?不要着急,我们接下来就会解决这个问题。

我们先来看下基本的策略模式图:

        

其实开始的时候,自己的头脑一直特别的乱,是因为我把这三种情况(正常就餐、未订餐就餐、订餐未就餐)一起来考虑的,让自己走进了一个死胡同。后来突然开窍了, 既然是这三种情况,我们为什么不一个个的考虑,然后逐个击破呢?所以,顺着这个思路,一个复杂的问题,拆分成多个不同的情况,每种情况再进行不同的处理。

处理流程:

当用户刷卡就餐时,进行查询判断,如果发现有订餐未就餐记录,则跳转到订餐未就餐的处罚界面(在这里查询订单状态为“未处理”的数量,如果发现大于0,则一定存在订餐未就餐的情况,同时这个字段也做为 处罚记录表 的一个字段,对于解决上述的复用问题,这个字段也起着关键的作用

下面是PunishContext的代码,这个项目运用了三层,底层用了抽象工厂。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using IDAL;
using System.Data;
using Entity;

namespace Strategy
{
    public class PunishContext
    {
        PunishSuper ps;
        IPunishData IPunishData;
        IActionOfPunish IActionOfPunish;
        public PunishContext(enPunisRecord PunishRecord)
        {
            IPunishData = DBFactory.DBFactory.CreatePunishData();
            IActionOfPunish = DBFactory.DBFactory.CreateActionOfPunish();
            int punishDataId = IActionOfPunish.GetPunisDataId(PunishRecord.PunishAction);

            //该方案下的处罚类型
            DataTable dt = IPunishData.SelectById(punishDataId);
            string type =dt .Rows[0]["punishType"].ToString().Trim();
            switch (type)
	        {
                case "现金处罚":
                    PunishRecord.PunishType = "现金处罚";
                    ps = new CashPunish(PunishRecord);
                    break;
                case "停卡处罚":
                    PunishRecord.PunishType = "停卡处罚";
                    ps = new StopCardPunish(PunishRecord);
                    break;
                case "警告后停卡处罚":
                    PunishRecord.PunishType = "警告后停卡处罚";
                    ps = new WarnStopCardPunish(PunishRecord);
                    break;
                case "警告后现金处罚":
                    PunishRecord.PunishType = "警告后现金处罚";
                    ps = new WarnCashPunish(PunishRecord);
                    break;
	        }
        }

        public enPunisRecord GetResult()
        {
            return ps.Punish();
        }
    }
}

个类的主要是作用是用来决定产生哪种处罚子类。

下面是punishSuper类的方法:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Entity;

namespace Strategy
{
    public abstract class PunishSuper
    {
        public abstract enPunisRecord Punish();
    }
}
为了举例说明,下面只展示 一个现金处罚类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Entity;
using IDAL;
using System .Data;
using System.Data.SqlClient;
using System.Configuration;

namespace Strategy
{
    public class CashPunish:PunishSuper
    {
        private enPunisRecord PunishRecord;
        public CashPunish(enPunisRecord PunishRecord)
        {
            this.PunishRecord = PunishRecord;
        }

        public override enPunisRecord Punish()
        {
            //根据处罚行为获取该处罚方案下的参数信息 datatable
            DataTable dt=GetParameter(PunishRecord.PunishAction);
            PunishRecord.PunishCash =PunishRecord.PunishCash+Convert.ToDouble(dt.Rows[0]["PunishCash"]);

            IPunishRecord IPunishRecord;
            IPunishRecord = DBFactory.DBFactory.CreatePunishRecord();
            IOrderInfo IOrderInfo;
            IOrderInfo = DBFactory.DBFactory.CreateOrderInfo();
            ICardInfo ICardInfo;
            ICardInfo = DBFactory.DBFactory.CreateCardInfo();

            SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["strConnection"].ConnectionString);
            SqlTransaction tran;
            conn.Open();
            tran = conn.BeginTransaction(System.Data.IsolationLevel.ReadCommitted);
            try
            {
                IPunishRecord.Insert(tran, PunishRecord);
                //通过orderNoEatCount判断,如果是对订餐未就餐的情况的话,那么就要更新状态为处理
                if (PunishRecord.OrderNoEatCount > 0)
                {
                    IOrderInfo.UpdateState(tran, PunishRecord.TeacherId);
                }
                ICardInfo.UpdateBalance(tran, GetCardNO(PunishRecord.TeacherId), PunishRecord.PunishCash * (-1));
                tran.Commit();
                conn.Close();
                return PunishRecord;
            }
            catch (Exception)
            {
                tran.Rollback();
                conn.Close(); 
                return null;
            }   
        }
        /// <summary>根据方案ID获取该方案下的信息
        /// 
        /// </summary>
        /// <param name="punishDataId"></param>
        /// <returns></returns>
        private DataTable GetParameter(string action)
        {
            IActionOfPunish IActionOfPunish;
            IActionOfPunish = DBFactory.DBFactory.CreateActionOfPunish();
            int punishDataId = IActionOfPunish.GetPunisDataId(PunishRecord.PunishAction);

            IPunishData IPunishData;
            IPunishData = DBFactory.DBFactory.CreatePunishData();
            return IPunishData.SelectById(punishDataId);
        }
        /// <summary>根据教师工号
        /// 
        /// </summary>
        /// <param name="teacherId"></param>
        /// <returns></returns>
        private string GetCardNO(string teacherId)
        {
            ITeacherInfo ITeacherInfo;
            ITeacherInfo = DBFactory.DBFactory.CreateTeacherInfo();
            return ITeacherInfo.SelectById(teacherId).Rows[0]["cardNO"].ToString();
        }
    }
}

其中的if条件判断也就是解决了这两种处罚情况下的代码复用问题的,里面用到了事务。

到此用策略模式便比较灵活地解决了这个问题,如果将来需求再怎么变化也能够灵活应对了。

  • 8
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 15
    评论
于芯智能X3网上订餐系统是面向医院、企业、工厂、政府机关单位等客户,专业研发的一套利用现代电子技术、无线技术、计算机技术以及网络技术,取代传统的纸和笔,进行电子点菜操作的系统,系统使用局域网网络、搭载内部OA系统,在有OA能到达的地方就能为职工提供网上订餐服务,后勤部门通过网络自助点餐软件实现高效的餐饮管理模式。 企业、单位、学校、医院等职工的就餐方式是到餐厅现场购买,由于职工工作繁忙,如果采用电话预约订餐,在中午就餐时间段,电话常常占线,并且餐厅人员通过纸和笔记录,手工制作食品制作计划、食品配送单等。由于职工人数多,食堂餐厅的接电话人员有限,通过手工记录订餐人员姓名、科室、所需食品名称和数量、金额、领取计划,数据量大,容易出错、费时费力,工作中出现错误,查对困难。 “X3网上订餐管理系统”解决了现实中存在的订餐问题,可以使每个职工自由订退餐,实时扣款,解决了各科室就餐欠费的问题,极大的减少管理成本。 管理管理员只要在后台轻轻一点,订餐数据即可显示,实时、动态,极为方便。后台自动统计,打印报表。从而节省饭堂开支,提高饭堂管理水平,在保证员工吃饱吃好的前提下,又能避免出错,省时高效、力行节约、节省人力成本。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值