一. 简单工厂模式概述
简单工厂模式并不是GoF《Design Patterns》一种中描述的23种设计模式之一,但是包含在了Cooper的《Introduction to Desgin Patterns in C#》中。可以毫不夸张的说,简单工厂模式是目前应用最多的模式。
简单工厂模式处理的是这样一种问题:有一系列功能及其相似的产品,在客户看来完全可以互相替代。客户需要使用的是其中一个产品,而他并不关心具体是哪一个。因此,客户不应该负有创建产品的责任——这个责任应该由产品来承担。因此,需要一个负责创建具体产品的工厂,为客户完成具体产品的创建工作。
用面向对象表述来说就是,有一组接口相同的类可以提供给客户端调用(实例化)。但是,客户端调用的时候,根本不关心(不需要知道)到底实例化的是哪个类。这个工作由一个工厂类来完成。工厂类是整个模式的核心,它根据客户的需要来动态决定创建哪一个类的实例。
简单工厂模式并不是GoF《Design Patterns》一种中描述的23种设计模式之一,但是包含在了Cooper的《Introduction to Desgin Patterns in C#》中。可以毫不夸张的说,简单工厂模式是目前应用最多的模式。
简单工厂模式处理的是这样一种问题:有一系列功能及其相似的产品,在客户看来完全可以互相替代。客户需要使用的是其中一个产品,而他并不关心具体是哪一个。因此,客户不应该负有创建产品的责任——这个责任应该由产品来承担。因此,需要一个负责创建具体产品的工厂,为客户完成具体产品的创建工作。
用面向对象表述来说就是,有一组接口相同的类可以提供给客户端调用(实例化)。但是,客户端调用的时候,根本不关心(不需要知道)到底实例化的是哪个类。这个工作由一个工厂类来完成。工厂类是整个模式的核心,它根据客户的需要来动态决定创建哪一个类的实例。
二. 简单工厂模式实例
假设我们需要向汽车租赁公司租赁汽车,汽车公司有许多品牌的汽车,但是我们并不特别关心这些。我们只需要给汽车公司一个电话“我需要一辆汽车”,租赁公司就会为我们选择一辆。选择的过程可能需要根据我们的要求,比如品牌,也可能只是根据租赁公司的情况(哪些汽车可用)随便给一辆。
用OOD的方法,首先我们有一个抽象的汽车的概念Car,那些具体的汽车(比如Benz、Audi)只是这个汽车的一个具体实现。汽车公司承担一个分配的职能,根据需要决定为客户提供哪一辆。如下图:
客户怎么通过汽车公司得到一辆汽车呢?很简单,它只需要用如下方式就可以了:
Car car=CarFactory.GetCar("Benz");
这样,我们就得到了一辆Benz汽车!
示例代码如下:
namespace SimpleFactory
... ... {
//抽象汽车概念
public abstract class Car
......{
public abstract void Run();
}
//具体汽车Benz
public class Benz : Car
......{
public override void Run()
......{
Console.WriteLine("A Benz is running!");
}
}
//具体汽车Audi
public class Audi : Car
......{
public override void Run()
......{
Console.WriteLine("An Audi is running!");
}
}
//汽车公司
public class CarFactory
......{
public static Car GetCar(string carName)
......{
if (carName.ToLower().Equals("benz"))
......{
return new Benz();
}
else
......{
return new Audi();
}
}
}
//客户
public class Client
......{
static void Main(string[] args)
......{
Car car = CarFactory.GetCar("Benz");
car.Run();
Console.ReadKey();
}
}
}
... ... {
//抽象汽车概念
public abstract class Car
......{
public abstract void Run();
}
//具体汽车Benz
public class Benz : Car
......{
public override void Run()
......{
Console.WriteLine("A Benz is running!");
}
}
//具体汽车Audi
public class Audi : Car
......{
public override void Run()
......{
Console.WriteLine("An Audi is running!");
}
}
//汽车公司
public class CarFactory
......{
public static Car GetCar(string carName)
......{
if (carName.ToLower().Equals("benz"))
......{
return new Benz();
}
else
......{
return new Audi();
}
}
}
//客户
public class Client
......{
static void Main(string[] args)
......{
Car car = CarFactory.GetCar("Benz");
car.Run();
Console.ReadKey();
}
}
}
三.简单工厂模式角色和结构
简单工厂模式的一般结构如下图:
-
Ab stractProduct :抽象产品角色, 定义了简单工厂所创建的具体对象的父类或它们共同拥有的接口。这个角色应该是一个抽象类,也可以是一个接口。
-
ProductA/B:具体产品角色,由工厂所能产生的具体产品,从抽象产品类继承。
-
SimpleFactory:简单工厂角色。这是简单公车模式的核心,它根据客户的需要动态创建具体的产品。
四. 简单工厂模式总结
简单工厂模式把创建具体类的功能封装在一个工厂类中来完成,对客户程序实现了产品细节的封装,降低了客户端对具体产品的依赖,降低了系统的耦合度。
不过,由于工厂类包含了对创建具体产品的逻辑,实际上依赖于具体的产品类。当需要增加新的产品的时候,如在上面的例子中增加具体的汽车Ford,需要修改工厂类代码以添加相应的逻辑。因此,简单工厂类不符合
OCP原则
的要求,因此并不是一个很好的OOD设计。也许正是因为这个原因,GoF并没有把简单工厂模式作为设计模式之一。
不过,现在仍有很多实际应用中应用简单工厂模式,并且通过配置文件等方式使得创建具体产品的方法CreateProductMethod不在硬编码,而是使用控制反转(Inversion of Control, IoC)或依赖注入(Dependency Injection, DI)的方法,从配置文件中读取需要创建的具体产品类——这就解决了简单工厂模式无法在具体产品方向上扩展的问题。