简单工厂模式
从父类派生出多个子类时,使用一个单独的类来做创造实例的过程,这就是工厂。
下面举出两个实例进行介绍简单工厂模式的应用。
简单计算器
每种计算都是获取数,返回结果的过程,故而可以将每种计算单独封装为一个类,并继承父类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
注意
工厂类虽然能解决这个问题,但是这份模式只是解决对象的创建问题,工厂包括了所有的收费方式,每次维护或者扩展都要改动这个工厂,可以使用策略模式改进程序。