一、超市收银系统:

在上一篇中简单介绍了简单工厂模式,在理论方面应该清楚了这是个什么东西用来处理什么情况和它的优缺点,现在来看看应用简单工厂模式的一个现实情境——超市收银系统。在现实生活中商品、仓库、超市、顾客就是一条链子,通过这条链子不论是顾客买商品或者是超市管理商品都得到非常方便的效果,超市也会有一些优惠的方案,这次我们就通过简单工厂模式来实现我们现实生活中超市收银的情况。

二、逻辑思路:

1、产品:

1-1、创建产品父类,产品有价格、名称、ID等公共属性。

1-2、创建各产品子类,继承于产品父类。

2、计算价格:

2-1、创建计算价格父类,抽象出计算总价方法。

2-2、创建计算价格无优惠子类。

2-3、创建计算价格满减优惠子类。

2-4、创建计算价格打折优惠子类。

3、仓库:

3-1、创建仓库类,给每个产品子类都创建一个集合(各自的货架)。

3-2、仓库需要有货才叫仓库,写出仓库进货方法。

3-3、超市有交易需向仓库拿货才能实现交易,写出根据货物名称和数量拿货方法。

3-4、仓库需要展示有什么货物,写出展示货物名称和数量方法。

4、超市:

4-1、写出根据用户买的货物计算总价钱的方法。

4-2、写出用户想使用哪种优惠的方法(简单工厂模式的实现)。

4-3、写出超市与顾客交互的方法(需要买什么、买多少、使用什么优惠)。

三、相关代码:

1、先创建产品父类:

        public ProductFather(string id, double price, string name)
        {
            this.ID = id;
            this.Price = price;
            this.Name = name;
        }
        public double Price { get; set; }
        public string Name { get; set; }
        public string ID { get; set; }

 1-1、创建产品各个子类,继承于产品父类(这里不一一写):

    class Acer:ProductFather
    {
        public Acer(string id,double price,string name):base(id,price,name)
        {

        }
    }

 2、抽象出计算价格父类,定义抽象获得总价方法:

    abstract class CalFather
    {
        public abstract double GetTotalMoney(double realMoney);
    }

 2-1、创建计算价格无任何折扣子类,继承于计算价格父类,重写获得总价方法:

    class CalNormal : CalFather
    {
        public override double GetTotalMoney(double realMoney)
        {
            return  realMoney;
        }
    }

 2-2、创建计算价格满减子类,继承于计算价格父类,重写获得总价方法:

    class CalMN : CalFather
    {
        public double M { get; set; }
        public double N { get; set; }
        public CalMN(double m,double n)
        {
            this.M = m;
            this.N = n;
        }
        public override double GetTotalMoney(double realMoney)
        {
            if (realMoney >= this.M)
            {
                return realMoney - (int)(realMoney / this.M) * this.N;
            }
            else
            {
                return realMoney;
            }
        }
    }

 2-3、创建计算价格打折子类,继承于计算价格父类,重写获得总价方法:

    class CalRate : CalFather
    {
        //折扣率
        public double Rate { get; set; }
        public CalRate(double rate)
        {
            this.Rate = rate;
        }
        public override double GetTotalMoney(double realMoney)
        {
            return realMoney * this.Rate;
        }
    }

 3、创建仓库类:

        //存储货物
        //List<SamSung> listSam = new List<SamSung>();
        //List<Acer> listAcer = new List<Acer>();
        //List<JiangYou> listJiangYou = new List<JiangYou>();
        //List<Banana> listBanana = new List<Banana>();
        //List<ProductFather> list = new List<ProductFather>();//全堆一起不好找

        List<List<ProductFather>> list = new List<List<ProductFather>>();

 3-1、在创建仓库对象的时候,向仓库添加货架:

        //list[0]存储Acer电脑
        //list[1]存储三星手机
        //list[2]存储酱油
        //list[3]存储香蕉
        //在创建仓库对象的时候,向仓库添加货架
        public CangKu()
        {
            list.Add(new List<ProductFather>());
            list.Add(new List<ProductFather>());
            list.Add(new List<ProductFather>());
            list.Add(new List<ProductFather>());
        }

 3-2、仓库进货方法:

        /// <summary>
        /// 进货
        /// </summary>
        /// <param name="strType"></param>
        /// <param name="count"></param>
        public void JinPros(string strType,int count)
        {
            for (int i = 0; i < count; i++)
            {
                switch (strType)
                {
                    case "Acer":list[0].Add(new Acer(Guid.NewGuid().ToString(),1000,"宏碁笔记本"));break;
                    case "SamSung":list[1].Add(new SamSung(Guid.NewGuid().ToString(), 2000, "棒之手机"));break;
                    case "JiangYou":list[2].Add(new JiangYou(Guid.NewGuid().ToString(), 10, "酱油"));break;
                    case "Banana":list[3].Add(new Banana(Guid.NewGuid().ToString(), 2, "香蕉"));break;
                }
            }
        }

 3-3、超市向仓库取货方法:

        /// <summary>
        /// 取货
        /// </summary>
        /// <param name="strType"></param>
        /// <param name="count"></param>
        /// <returns></returns>
        public ProductFather[] QuPros(string strType,int count)
        {
            ProductFather[] pros = new ProductFather[count];
            for (int i = 0; i < count; i++)
            {
                switch (strType)
                {
                    case "Acer":
                        pros[i] = list[0][0];
                        list[0].RemoveAt(0); break;
                    case "SamSung":
                        pros[i] = list[1][0];
                        list[1].RemoveAt(0); break;
                    case "JiangYou":
                        pros[i] = list[2][0];
                        list[2].RemoveAt(0); break;
                    case "Banana":
                        pros[i] = list[3][0];
                        list[3].RemoveAt(0); break;
                }
            }
            return pros;
        }

 3-4、展示货物方法:

        /// <summary>
        /// 展示货物
        /// </summary>
        public void ShowPros()
        {
            foreach (var item in list)
            {
                Console.WriteLine("我们超市有:" + item[0].Name + "," + "\t" + "" + item.Count + "个," + "\t" + "每个" + item[0].Price + "");
            }
        }

 4、创建超市类:

        //创建仓库对象
        CangKu ck = new CangKu();

        //创建超市对象的时候,给仓库的货架上导入货物
        public SuperMarket()
        {
            ck.JinPros("Acer", 1000);
            ck.JinPros("SamSung", 1000);
            ck.JinPros("JiangYou", 1000);
            ck.JinPros("Banana", 1000);
        }

 4-1、写出计算总价方法:

        /// <summary>
        /// 根据用户买的货物计算总价钱
        /// </summary>
        /// <param name="pros"></param>
        /// <returns></returns>
        public double GetMoney(ProductFather[] pros)
        {
            double realMoney = 0;
            for (int i = 0; i < pros.Length; i++)
            {
                realMoney += pros[i].Price;
            }
            return realMoney;
        }

 4-2、写出顾客和服务员交互方法,模拟超市交易:

        /// <summary>
        /// 跟顾客交互的过程
        /// </summary>
        public void AskBuying()
        {
            Console.WriteLine("欢迎光临,请问您需要些什么");
            Console.WriteLine("我们有Acer/SamSung、JiangYou、Banana");
            string strType = Console.ReadLine();
            Console.WriteLine("您需要多少");
            int count = Convert.ToInt32(Console.ReadLine());
            //去仓库取货物
            ProductFather[] pros = ck.QuPros(strType, count);
            //下面该计算价钱了
            double realMoney = GetMoney(pros);
            Console.WriteLine("您总共应付{0}元",realMoney);
            Console.WriteLine("请选择您的打折方式 1--不打折 2--打9折 3--打8.5折 4--买300送50 5--满500送100");
            string input = Console.ReadLine();
            //通过简单工厂的设计模式,根据用户的选择获得一个打折对象
            CalFather cal = GetCal(input);
            double totalMoney = cal.GetTotalMoney(realMoney);
            Console.WriteLine("打完折后,您应付{0}元",totalMoney);
            Console.WriteLine("以下是您的购物信息");
            foreach (var item in pros)
            {
                Console.WriteLine("货物名称:"+item.Name+""+"\t"+"货物单价:"+item.Price+""+"\t"+"货物编号:"+item.ID);
            }
        }

 4-3、简单工程模式实现,创建计算价格父类,写出根据情况具体实现哪种优惠方法:

        /// <summary>
        /// 根据用户的选择打折方式返回一个打折对象
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public CalFather GetCal(string input)
        {
            CalFather cal = null;
            switch (input)
            {
                case "1": cal = new CalNormal();break;//不参加任何优惠
                case "2": cal = new CalRate(0.9);break;//打9折
                case "3": cal = new CalRate(0.85);break;//打8.5折
                case "4": cal = new CalMN(300, 50);break;//满300减50
                case "5": cal = new CalMN(500, 100);break;//满500减100
            }
            return cal;
        }

 5、调用超市类,实现超市收银系统:

            //创建超市对象
            SuperMarket sm = new SuperMarket();
            //展示货物
            sm.ShowPros();
            //跟用户交互
            sm.AskBuying();
            Console.ReadKey();

 四、总结:

通过这个简单的小应用我们更加熟悉了简单工厂的设计模式,也更明显看出了它的优缺点,它更方便快捷实现功能的同时但也会因为其中一层出现问题就会整个系统瘫痪。