一. 工厂方法模式简介
在简单工厂模式中,由一个工厂类(实际上是其中的某一个具体方法)负责决定实例化哪一个具体产品,从而接触客户和具体产品类直接的依赖关系。而工厂方法模式对这种思想进行了进一步的扩展,把这个实例化产品的方法抽象化(从而也抽象化了这个工厂类),把实例化哪一个具体产品类的决策延迟到它的子类中去。也就是说,这个抽象方法只定义了应该创建一个什么类(抽象),让子类去决定创建哪一个对象。
GoF的《设计模式》中这样描述工厂方法模式:
定义一个用户创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。
二. 工厂方法模式示例
还以简单工厂模式中提到的向汽车租赁公司租用车辆的例子。现在,这个汽车租赁公司由于业务扩展的很快,有了几个分公司,这几个分公司的业务是一致的,不过提供的车辆不同。这个时候,总公司不再具体处理给客户提供哪一辆车,而把这个权利下放给它的子公司来完成。如下图:
这个应用的代码如下,注意客户调用的方式:
namespace
FactoryMethod
... {
//抽象汽车概念
public abstract class Car
...{
public abstract void Run();
}
//Audi
public class Audi : Car
...{
public override void Run()
...{
Console.WriteLine("An Audi is running!");
}
}
//Benz
public class Benz : Car
...{
public override void Run()
...{
Console.WriteLine("A Benz is running!"); ;
}
}
//总公司
public abstract class RentCenter
...{
//总公司定义的方法——工厂方法
public abstract Car GetCar();
}
//Audi租赁公司
public class AudiRentCenter : RentCenter
...{
//Audi租赁公司的具体实现方法
public override Car GetCar()
...{
return new Audi();
}
}
//Benz租赁公司
public class BenzRentCenter : RentCenter
...{
public override Car GetCar()
...{
return new Benz();
}
}
//客户
public class Client
...{
public static void Main(string[] args)
...{
RentCenter rentCenter = new AudiRentCenter();
Car car = rentCenter.GetCar();
car.Run();
Console.ReadKey();
}
}
}
... {
//抽象汽车概念
public abstract class Car
...{
public abstract void Run();
}
//Audi
public class Audi : Car
...{
public override void Run()
...{
Console.WriteLine("An Audi is running!");
}
}
//Benz
public class Benz : Car
...{
public override void Run()
...{
Console.WriteLine("A Benz is running!"); ;
}
}
//总公司
public abstract class RentCenter
...{
//总公司定义的方法——工厂方法
public abstract Car GetCar();
}
//Audi租赁公司
public class AudiRentCenter : RentCenter
...{
//Audi租赁公司的具体实现方法
public override Car GetCar()
...{
return new Audi();
}
}
//Benz租赁公司
public class BenzRentCenter : RentCenter
...{
public override Car GetCar()
...{
return new Benz();
}
}
//客户
public class Client
...{
public static void Main(string[] args)
...{
RentCenter rentCenter = new AudiRentCenter();
Car car = rentCenter.GetCar();
car.Run();
Console.ReadKey();
}
}
}
三.工厂方法模式角色和结构
工厂方法模式的一般结构如下图:
-
AbstractProduct:抽象产品角色, 定义了具体对象的父类或它们共同拥有的接口。这个角色应该是一个抽象类,也可以是一个接口。
-
ConcreteProductA/B:具体产品角色,所能产生的具体产品,从抽象产品类继承。
-
AbstractCreator:抽象建造者角色,它是一个抽象类(或接口),包含工厂方法FactoryMethod()的抽象定义。它是工厂方法模式的核心。
-
ConcreteCreatorA/B:具体建造者角色,从抽象建造者继承,具体实现工厂方法,建立具体产品。
四. 工厂方法模式总结
在简单工厂模式中提到,由于简单工厂类负责具体产品的创建,因此在需要添加新产品的时候必须修改工厂类;工厂方法模式通过对工厂方法的抽象,将创建具体产品的职能放到了子类中实现,因此在需要添加新产品的时候,可以简单的添加一个具体建造者类就可以了,因此完全满足了
OCP的要求。
工厂方法模式通常对于每一个具体的产品都创建一个具体的建造者,因此建造者类与产品类往往具有平行的等级结构,它们之间一一对应(如
ConcreteCreatorA
对应
ConcreteProductA
)
。
工厂方法模式可以适用于以下情况:
-
当一个类不知道它所必须创建的对象的类的时候。
-
当一个类希望由它的子类来指定它所创建的对象的时候。
-
当类将创建对象的职责委托给多个帮助子类中的某一个,并且你希望将哪一个帮助子类是代理者这一信息局部化的时候。
上面是从《设计模式》中摘抄的,想想也就只有这个说法最科学。
工厂方法模式中,建造者类的工厂方法可以不局限于一个。比如,出租公司还同时出租自行车,当然也可以再加一个工厂方法GetBicycle(),这也是工厂方法模式完全允许的——这几乎就是抽象工厂模式。值得一提的是,这个例子并不恰当。出租自行车和出租汽车互不相关,根据
ISP原则,应该分开设计成两个建造者。