前言
回顾上篇的设计模式之-简单工厂模式 我们可以从中发现一些问题。
先看看以计算器为例的简单工厂的结构图如下:

那此时我们换成工厂模式呢?我们先看看工厂的结构图:

承接上篇计算器为例,我们需要新建一个工厂接口
/// <summary>
/// 构建一个工厂接口
/// </summary>
interface IFactory
{
Operaion CreateOperation();
}
然后呢,为加减乘法各建一个具体的工厂实现接口
//然后加减乘法各建一个具体的工厂实现接口
class AddFactory : IFactory
{
public Operaion CreateOperation()
{
return new OpertionAdd();
}
}
class SubFactory : IFactory
{
public Operaion CreateOperation()
{
return new OperationSub();
}
}
class MulFactory : IFactory
{
public Operaion CreateOperation()
{
return new OperationMul();
}
}
class DivFactory : IFactory
{
public Operaion CreateOperation()
{
return new OperationDiv();
}
}
客户端调用
static void Main(string[] args)
{
try
{
Console.Write("请输入数字A:");
string strNumberA = Console.ReadLine();
Console.Write("请选择运算符号(+、-、*、/):");
string strOperate = Console.ReadLine();
Console.Write("请输入数字B:");
string strNumberB = Console.ReadLine();
//调用工厂进行计算
IFactory operFactory = new AddFactory();
Operaion oper = operFactory.CreateOperation();
oper.NumberA =double.Parse(strNumberA);
oper.NumberB =double.Parse(strNumberB);
//返回计算结果
var strResult = oper.GetResult();
Console.WriteLine("结果是:" + strResult);
Console.ReadKey();
}
catch (Exception ex)
{
Console.WriteLine("您的输入有错:" + ex.Message);
}
}
Why?为什么要这么写呢?上一篇的简单工厂已经很容易就实现了这个效果,为什么还要新加这个工厂来“复杂”化这个问题呢?
其实不然,简单工厂模式的最大优点在于工厂类中包含了必要的逻辑判断,根据客户端的选择条件动态实例化相关的类,对于客户端来说,去除了具体产品的依赖。
就像计算器,客户端不用管该用哪个类的实例,只需要把"+"给工厂,工厂自动就给出了相应的实例,客户端只要去做运算就可以了。但问题也在这里,如果要加一个‘求M数的N次方’功能,我们是一定要给运算工厂类的方法里加‘Case’分支条件的,既是修改了原有的类。这样就违背了我们开放-封闭原则。于是工厂方法就来了


这样的话,我们要增加‘求M数的N次方’的功能时,就不需要更改原有的工厂类了,只需要增加此功能的运算类和相应的工厂类就可以了。这就完全符合开放-封闭原则。
巩固
以大学生学习‘雷锋’好人好事为例。首先是雷锋类:拥有扫地、洗衣、买米等方法
//雷锋类
class LeiFeng
{
public void Sweep()
{
Console.WriteLine("扫地");
}
public void Wash()
{
Console.WriteLine("洗衣");
}
public void BuyRice()
{
Console.WriteLine("买米");
}
}
然后‘学雷锋大学生’类继承‘雷锋’类
/// <summary>
/// 学雷锋的大学生,继承‘雷锋’
/// </summary>
class Undergraduate : LeiFeng
{ }
然后客户端实现
LeiFeng xueleifeng = new Undergraduate();
xueleifeng.BuyRice();
xueleifeng.Sweep();
xueleifeng.Wash();
有一个问题,如果有三个人去学‘雷锋做好事,该怎么写呢?’
难道是写成?
LeiFeng xueleifeng = new Undergraduate();
xueleifeng.BuyRice();
LeiFeng xueleifeng2 = new Undergraduate();
xueleifeng.Sweep();
LeiFeng xueleifeng3 = new Undergraduate();
xueleifeng.Wash();
此时,就非常不合适了,老人不需要知道是谁来做好事,他只需要知道学雷锋的人来帮忙就可以ile,这样写我们需要更改多个实例化的地方。我们应该增加‘社区志愿者’类
/// <summary>
/// 社区志愿者
/// </summary>
class Volunteer : LeiFeng
{ }
再写简单工厂类
/// <summary>
/// 简单雷锋工厂
/// </summary>
class SimpleFactory
{
public static LeiFeng CreateLeiFeng(string type)
{
LeiFeng result = null;
switch (type)
{
case "学雷锋的大学生":
result = new Undergraduate();
break;
case "社区志愿者":
result=new Volunteer();
break;
}
return result;
}
}
客户端的代码,如果要换,就只需要换‘学雷锋的大学生为‘社区志愿者’’
//简单工厂模式
LeiFeng studentA = SimpleFactory.CreateLeiFeng("学雷锋的大学生");
studentA.BuyRice();
LeiFeng studentB = SimpleFactory.CreateLeiFeng("学雷锋的大学生");
studentA.Sweep();
LeiFeng studentC = SimpleFactory.CreateLeiFeng("学雷锋的大学生");
studentA.Wash();
好,此时我们就发现,在任何实例化的时候写出这个工厂的代码,这里有重复,就出现了坏的味道,此时,我们再用工厂模式写一遍。
/// <summary>
/// 雷锋工厂
/// </summary>
interface IFactory
{
LeiFeng CreateLeiFeng();
}
/// <summary>
/// 学雷锋的大学生工厂
/// </summary>
class UndergraduateFacotry : IFactory
{
public LeiFeng CreateLeiFeng()
{
return new Undergraduate();
}
}
/// <summary>
/// 社区志愿者工厂
/// </summary>
class VolunteerFactory : IFactory
{
public LeiFeng CreateLeiFeng()
{
return new Volunteer();
}
}
客户端调用的时候只需要如下就可以了
//工厂方法模式
IFactory factory = new UndergraduateFacotry();//要换成‘社区志愿者’,修改这里即可
LeiFeng student = factory.CreateLeiFeng();
student.BuyRice();
student.Sweep();
student.Wash();
