zoukankan      html  css  js  c++  java
  • 大话设计模式-简单工厂模式

    简单工厂模式

    从父类派生出多个子类时,使用一个单独的类来做创造实例的过程,这就是工厂。

    下面举出两个实例进行介绍简单工厂模式的应用。


    简单计算器

    每种计算都是获取数,返回结果的过程,故而可以将每种计算单独封装为一个类,并继承父类Operation。在父类中声明一个虚方法GetResult,每种计算子类都要重写父类该方法以进行自己的计算。

    父类计算类:Operation

    public class Operation{
        //两数的属性、获得结果虚方法
        public double NumbleA { get; set; }
        public double NumbleB { get; set; }
        public virtual double GetResult() => default(double);       
    }

    派生的子类:OperationAdd、Sub、Mul、Div

    class OperationAdd : Operation{
        public override double GetResult() => NumbleA + NumbleB;
    }
    class OperationSub : Operation{
        public override double GetResult() => NumbleA - NumbleB;
    }
    class OperationMul : Operation{
        public override double GetResult() => NumbleA * NumbleB;
    }
    class OperationDiv : Operation{
        public override double GetResult(){
            if (NumbleB == 0) throw new Exception("除数不能为0");
            return NumbleA / NumbleB;
        }
    }

    工厂类:OperationFactory

    class OperationFactory{
        //根据输入的运算符进行判断生成哪种子类的静态方法
        public static Operation CreateOperate(string operate){
            Operation oper = null;
            switch (operate){
                case "+":
                    oper = new OperationAdd();
                    break;
                case "-":
                    oper = new OperationSub();
                    break;
                case "*":
                    oper = new OperationMul();
                    break;
                case "/":
                    oper = new OperationDiv();
                    break;
            }
            return oper;
        }
    }

    测试类:Program

    class Program{
        static void Main(string[] args){
            Console.WriteLine("请输入一个数:");
            double n1=Convert.ToDouble(Console.ReadLine());
            Console.WriteLine("请输入运算符:");
            var of=OperationFactory.CreateOperate(Console.ReadLine());
            Console.WriteLine("请输入一个数");
            double n2 = Convert.ToDouble(Console.ReadLine());
            of.NumbleA = n1;
            of.NumbleB = n2;
            Console.WriteLine($"运算结果为:{of.GetResult()}");
            Console.ReadKey();
        }
    }

    测试结果:控制台

    请输入一个数:
    5
    请输入运算符:
    /
    请输入一个数
    2
    运算结果为:2.5

    商场促销

    商场促销的分类不应该细分折扣或者满减级别,这样类就特别多,分类的基础是抽象,具有相同属性和功能的对象的抽象集合才是类。

    商场促销有原价、打折、满减等手段,收银台需要根据不同的活动,将总价带入不同优惠的计算公式中得出最终的价格,所以打折算法才应该是一个类。

    父类:现金收费抽象类

    提供了一个接受现金抽象方法

    abstract class CashSuper{
        public abstract double AcceptCash(double money);
    }

    子类:正常、打折、满减类

    根据不同的优惠,将优惠方法分为若干个类,这些类都要继承现金收费抽象类并重写接受现金抽象方法。

    class CashNormal : CashSuper{
        //返回原价
        public override double AcceptCash(double money) => money;
    }
    class CashRebate : CashSuper{
        //声明、初始化折扣
        private double moneyRebate = 1d;
        public CashRebate(double moneyRebate)=>this.moneyRebate = moneyRebate;
        //重写方法,计算折扣额
        public override double AcceptCash(double money) => money * moneyRebate;
    }
    class CashReturn : CashSuper{
        //声明、初始化满额和减额
        private double moneyCondition = default(double);
        private double moneyReturn = default(double);
        public CashReturn(double moneyCondition, double moneyReturn){
            this.moneyCondition = moneyCondition;
            this.moneyReturn = moneyReturn;
        }
        //重写方法,计算返回满减额
        public override double AcceptCash(double money){
            //将金额除以满额得到的数取整,乘以减额,得到满减额
            if (money >= moneyCondition)
                return money - Math.Floor(money / moneyCondition) * moneyReturn;
            return money;
        }
    }

    工厂类:现金工厂类

    根据选择的不同优惠,创建对应的现金收费类的子类

    class CashFactory{
        public static CashSuper CreateCashAccept(string type){
            CashSuper cs = null;
            switch (type){
                case "1":
                    cs = new CashNormal();//原价
                    break;
                case "2":
                    cs = new CashRebate(0.8);//八折
                    break;
                case "3":
                    cs = new CashReturn(300,100);//满300返100
                    break;
            }
            return cs;
        }
    }

    测试类:程序类

    测试数据

    class Program{
        static void Main(string[] args){
            Console.Write("请输入商品单价:");
            double foodSprice=double.Parse(Console.ReadLine());
            Console.Write("请输入商品数量:");
            double fooeNum = double.Parse(Console.ReadLine());
            Console.WriteLine($"1:原价{Environment.NewLine}2:八折{Environment.NewLine}3:满300返100");
            Console.Write("请选择优惠方式:");
            CashSuper cp=CashFactory.CreateCashAccept(Console.ReadLine());
            Console.WriteLine(cp.AcceptCash(foodSprice*fooeNum));
            Console.ReadKey();
        }
    }

    测试结果:控制台

    请输入商品单价:200
    请输入商品数量:5
    1:原价
    2:八折
    3:满300返100
    请选择优惠方式:3
    700

    注意

    工厂类虽然能解决这个问题,但是这份模式只是解决对象的创建问题,工厂包括了所有的收费方式,每次维护或者扩展都要改动这个工厂,可以使用策略模式改进程序。

  • 相关阅读:
    面向对象
    Spring学习(十四)----- Spring Auto Scanning Components —— 自动扫描组件
    Spring学习(十三)-----Spring 表达式语言(Spring EL)
    Spring学习(十二)-----Spring @PostConstruct和@PreDestroy实例
    Spring学习(十二)-----Spring Bean init-method 和 destroy-method实例
    学习计划
    Spring学习(十一)-----Spring使用@Required注解依赖检查
    Spring学习(十)-----Spring依赖检查
    Spring学习(九)-----Spring bean配置继承
    Spring学习(八)-----Spring注入值到集合类型的例子
  • 原文地址:https://www.cnblogs.com/errornull/p/10012252.html
Copyright © 2011-2022 走看看