1. 引入
2. 工厂方法实现计算器功能
以前面博客工厂模式之简单工厂 https://www.cnblogs.com/mo-lu/p/11062752.html 中提出的实现计算器功能为例, 用工厂方法进行实现, 结构图如下图 1 所示, 代码如下:
简单工厂模式中分支与工厂类耦合, 需要增加新的运算类时, 需要在工厂方法中的 switch..case 中添加判断条件, 根据依赖倒转原则, 将工厂类与运算进行解耦, 因此, 抽象出一个接口, 接口中只有一个方法, 创建抽象产品的工厂方法. 之后, 所有要生产具体类的工厂去实现这个接口. 这样简单工厂模式的工厂类, 变成了一个抽象工厂接口和多个生产类的具体工厂. 此时, 简单工厂模式的工厂类变成一个工厂抽象接口和多个具体生成对象的工厂.
- class Operate
- {
- private double _num1;
- private double _num2;
- public double num1
- {
- get { return num1; }
- set { num1 = _num1; }
- }
- public double num2
- {
- get { return num2; }
- set { num2 = _num2; }
- }
- public virtual double getResult(double num1, double num2)
- {
- double result = 0.0;
- return result;
- }
- }
- class Add : Operate
- {
- public override double getResult(double n1, double n2)
- {
- return n1 + n2;
- }
- }
- class Sub : Operate
- {
- public override double getResult(double n1, double n2)
- {
- return n1 - n2;
- }
- }
- class Multiply : Operate
- {
- public override double getResult(double n1, double n2)
- {
- return n1 * n2;
- }
- }
- class Divide : Operate
- {
- public override double getResult(double n1, double n2)
- {
- if (n2 == 0)
- throw new Exception("除数不能为 0");
- return n1 / n2;
- }
- }
- interface IFactory
- {
- Operate createOperate();
- }
- class AddFactory:IFactory
- {
- public Operate createOperate()
- {
- return new Add();
- }
- }
- class SubFactory : IFactory
- {
- public Operate createOperate()
- {
- return new Sub();
- }
- }
- class MultiplyFactory : IFactory
- {
- public Operate createOperate()
- {
- return new Multiply();
- }
- }
- class DivideFactory : IFactory
- {
- public Operate createOperate()
- {
- return new Divide();
- }
- }
- class Program
- {
- static void Main(string[] args)
- {
- IFactory operateFactory = new AddFactory();
- Operate ope = operateFactory.createOperate();
- double result = ope.getResult(1.0,2.0);
- Console.WriteLine("{0}",result);
- Console.Read();
- }
- }
在工厂方法模式中, 选择用哪个工厂实现运算类, 由原来的工厂类内部转移到客户端判别.
3. 情景实现
情景介绍: 某同学 "学雷锋" 以学习雷锋的名义在医院做义工 (打扫, 洗衣, 买饭), 在他生病的时候, 其他人以同样的名义代替他去, 首先使用简单工厂模式实现.
分析发现, 该场景中可以把 "学雷锋" 和其他人抽象出一个 "雷锋" 类, 拥有打扫, 洗衣, 买饭的方法, 代码如下:
- class LeiFeng
- {
- public void Sweep()
- {
- Console.WriteLine("I am sweeping");
- }
- public void Wash()
- {
- Console.WriteLine("I am washing");
- }
- public void Cook()
- {
- Console.WriteLine("I am cooking");
- }
- }
- class Student:LeiFeng
- {
- }
- static void Main(string[] args)
- {
- LeiFeng lf=new Student();
- lf.Cook();
- lf.Sweep();
- lf.Wash();
- Console.WriteLine("Hello World!");
- }
然而, 如果有多个学生学雷锋做好事时, 需要进行多次实例化, 会造成大量重复代码以及创建对象的资源消耗. 而对医院病人来说, 不需要知道具体的对象是谁, 只需要知道是学雷锋的人帮忙就好. 此外, 有其他社会人士 "志愿者" 学雷锋做好事, 需要再新建一个类继承 LieFeng, 由雷锋工厂决定实例化谁, 这是简单工厂模式的实现, 具体如下:
- class SimpleFactory
- {
- public static LeiFeng createObject(string type)
- {
- LeiFeng result = null;
- switch (type)
- {
- case "学雷锋的大学生":
- result = new Student(); break;
- case "社区志愿者":
- result=new Volunteer();break;
- }
- return result;
- }
- }
- class Volunteer:LeiFeng
- {
- }
- static void Main(string[] args)
- {
- LeiFeng stud = SimpleFactory.createObject("学雷锋的大学生");
- stud.Sweep();
- LeiFeng stud2 = SimpleFactory.createObject("社区志愿者");
- stud2.Cook();
- Console.WriteLine("Hello World!");
- }
上述实现为简单工厂模式, 将其更改为工厂方法模式, 全部代码如下:
- interface SimpleFactory
- {
- LeiFeng CreateLeiFeng();
- }
- class StudengFactory:SimpleFactory
- {
- public LeiFeng CreateLeiFeng()
- {
- return new Student();
- }
- }
- class VolunteerFactory
- {
- public LeiFeng CreateLeiFeng()
- {
- return new Volunteer();
- }
- }
- class LeiFeng
- {
- public void Sweep()
- {
- Console.WriteLine("I am sweeping");
- }
- public void Wash()
- {
- Console.WriteLine("I am washing");
- }
- public void Cook()
- {
- Console.WriteLine("I am cooking");
- }
- }
- class Student:LeiFeng
- {
- }
- class Volunteer:LeiFeng
- {
- }
- static void Main(string[] args)
- {
- SimpleFactory sf=new StudengFactory();
- LeiFeng studeng = sf.CreateLeiFeng();
- studeng.Sweep();
- studeng.Wash();
- Console.WriteLine("Hello World!");
- }
- View Code
4. 总结
工厂方法模式主要由 4 部分组成:
抽象工厂角色. 是工厂方法模式的核心, 与应用程序无关, 是具体工厂角色必须实现的接口或必须继承的父类.(IFactory)
具体工厂角色. 包含和具体逻辑有关的代码. 客户端调用, 返回产品实例.(如 AddFactory)
抽象产品角色. 是产品接口 (如 Operation).
具体产品角色. 具体工厂角色所创建的对象就是此角色的实例 (如 AddOperate 类).
简单工厂模式和工厂方法模式的区别:
简单工厂模式中工厂类中包含必要的逻辑判断, 根据客户说的选择条件实例化相关类, 客户端与具体产品没有依赖. 而工厂方法模式实现时, 客户端需要决定实例化哪个工厂来实现运算类, 但是逻辑判断在客户端进行.
工厂方法模式是简单工厂模式的衍生, 解决了简单工厂模式违反 "开闭" 原则的问题, 并实现了可扩展, 能够解决更复杂的层次结构, 可用于产品结果复杂的场合.
来源: http://www.bubuko.com/infodetail-3107022.html