- 携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第2天,点击查看活动详情
前言
工厂方法模式(Factort Method)是一种常用的类创建型设计模式。
简单工厂模式
聊到工厂方法必须要说到的就是简单工厂模式,工厂类是整个模式的关键。在使用的时候仅需要传入参数,让工厂类去创建实例,无需去管这些对象究竟如何创建及如何组织的。
- 举一个例子,A运输公司在最初运营的时候由于资金问题采用了三轮车送货,此时我们需要创建一个抽象类Transport定义一个Delivery虚方法,再创建一个Tricycle类继承Transport类并且实现Delivery方法,然后实例化Tricycle类调用Delivery方法,代码如下!
// 定义抽象类
public abstract class Transport
{
public virtual void Cargo() { }
}
public class Tricycle : Transport
{
public override void Cargo()
{
Console.WriteLine("使用三轮车送货中······");
}
}
static void Main(string[] args)
{
//调用
Tricycle tricycle = new Tricycle();
tricycle.Cargo();
}
- A运输公司由于发展迅速,需要提供运输效率,特意采用国产电动货车支持新能源,代码在上面基础做出如下改变!
public class Minivan : Transport
{
public override void Cargo()
{
Console.WriteLine("使用小货车送货中······");
}
}
static void Main(string[] args)
{
//调用
Tricycle tricycle = new Tricycle();
tricycle.Cargo();
Minivan minivan = new Minivan();
minivan.Cargo();
}
传统写法会造成什么问题呢?无疑是创建和使用太过于耦合了,并且没有地方来统一管理会导致如果使用地方较多,会产生大量的重复代码。接下来我们使用简单工厂来实现看看。
- 创建工厂CargoFactort类
public class CargoFactort
{
// 参数为CarType 根据参数自动实例化类
public Transport CreateCargo(CarType type)
{
Transport transport = null;
switch (type)
{
case CarType.Tricycle:
transport = new Tricycle();
break;
case CarType.Minivan:
transport = new Minivan();
break;
default:
break;
}
return transport;
}
}
- 调用:无需实例化,直接调用工厂即可,也不用管对象是如何创建的。
static void Main(string[] args)
{
var tricycle = CargoFactort.CreateCargo(CarType.Tricycle);
tricycle.Cargo();
}
- 还是上面场景,A运输公司由于客户单量过多小货车无法满足需求,又订购了一批大卡车,此时我们项目做出如下修改:新增卡车类Truck实现Cargo方法,在工厂类Switch新增节点。
switch (type)
{
case CarType.Tricycle:
transport = new Tricycle();
break;
case CarType.Truck: // 新增卡车类节点
transport = new Truck();
break;
case CarType.Minivan:
transport = new Minivan();
break;
default:
break;
}
疑问? 如果直接修改工厂类会产生什么问题呢,违背了软件设计原则(开闭原则)。
开闭原则:一个软件实体,如类、模块和函数应该对扩展开放,对修改关闭。换句话说就是当你的类独立了就不应该修改它,只能提供方法去扩展它。
工厂方法模式
针对上述问题衍生出了工厂方法模式,完全实现了开-闭原则,适用于更为复杂的场景。工厂方法模式的核心结构有四个角色,分别如下。
- 抽象工厂:是工厂方法模式的核心,类声明返回产品对象的工厂方法。 该方法的返回对象类型必须与产品接口相匹配。
- 具体工厂:抽象工厂的实现, 使其返回不同类型的产品。
- 抽象产品:将会对接口进行声明。 对于所有由创建者及其子类构建的对象, 这些接口都是通用的。
- 具体产品:抽象产品的实现
类图1-1 如上(百度百科)
- 根据如上概念,我们讲上面业务场景进行代码优化如下
static void Main(string[] args)
{
TransportCreator transport = new TruckFactory();
Transport truck = transport.CreateTransport();
truck.Cargo();
}
//产品
public abstract class Transport
{
public abstract void Cargo();
}
// 创建者
public abstract class TransportCreator
{
public abstract Transport CreateTransport();
}
// 具体产品
public class Truck : Transport
{
public override void Cargo()
{
Console.WriteLine("使用卡车送货中······");
}
}
//具体创建者
public class TruckFactory : TransportCreator
{
public override Transport CreateTransport()
{
return new Truck();
}
}
如果需要在实现一个三轮车,只需要创建一个具体创建者TricycleFactory,新增一个具体产品Tricycle实现Cargo方法即可。
总结
工厂方法将创建产品的代码与实际使用产品的代码分离, 从而能在不影响其他代码的情况下扩展产品创建部分代码,解决了简单工厂模式违背的开闭原则。但是不难看出,应用工厂方法模式需要引入许多新的类, 代码结构会变得复杂起来。