前面提到了简单工厂,由于简单工厂的缺点:违背开放-封闭原则和单个类(工厂类)职责过多,工厂方法是简单工厂的抽象,克服了简单工厂的缺点。
概念:
工厂方法模式(Factory Method),定义一个用于创建对象的接口,让子类决定实例化哪个类。工厂方法使一个类的实例化延迟到其子类。
工厂方法模式根据目的划分是创建型模式,根据范围准则来分就是主要作用于类的。6个创建型就只有工厂方法模式是作用于类的。
而所谓的类模式就是指,类和子类之间的关系,是通过继承建立的,是静态的,在编译时刻便确定下来了。而几乎所有的模式都使用继承机制,所以“类模式”指的是那些集中于处理类间关系的模式。详情请见。Java设计模式分类不明白也没事,也不是很重要。
UML类图:
分析一下:工厂方法的角色有,工厂方法Creator(抽象类or接口)和具体工厂方法类ConcreteCreator(N个),以及一个抽象类/接口,用来定义工厂方法创建的对象,Product,然后就是具体的产品(N个)。
与简单工厂相比,就是简单工厂没有ConcreteCreator(具体工厂),所以简单工厂的Creator工厂类的职责就多。
代码实现:
还是汽车的例子。为了简单,还是那两种汽车,奔驰和宝马。不同的是,因为一家工厂生产两种汽车,忙不过来,所以学习单一职责原则,多开几家工厂,一家工厂只生产一种车子。然后就有两家工厂,奔驰工厂和宝马工厂。而且这样的话,如果以后再想增加奥迪,就只用增加奥迪工厂就好了。类图就如下所示:
代码如下:
namespace CarFactoryMethod
{
class Program
{
static void Main(string[] args)
{
//最后,客户端,作用创建车子。
//首先要实例化具体工厂.
//然后具体工厂创建具体的车,
//具体的车创建完成了,自己展示下.
CarFactory benzFactory = new BenzFactory();
ICar benz=benzFactory.CarCreate();
benz.Show();
CarFactory bmwFactory = new BMWFactory();
ICar bmw = bmwFactory.CarCreate();
bmw.Show();
Console.Read();
}
}
//首先还是抽象产品角色,汽车接口(产品角色都没变,不管抽象产品还是具体产品)
interface ICar
{
void Show();
}
//然后是两个具体产品角色,宝马和奔驰,他们都要实现ICar接口
class BMW:ICar
{
public void Show()
{
//内容很简单,只是输出一句话
Console.WriteLine("一辆宝马诞生了!!!");
}
}
//Benz类
class Benz:ICar
{
public void Show()
{
Console.WriteLine("我是一辆奔驰!!!");
}
}
//以上的类和简单工厂的一样,
//工厂方法的工厂类和简单工厂的不一样。
abstract class CarFactory
{
//是个抽象方法
public abstract ICar CarCreate();
}
//新开的两个工厂
//宝马工厂
class BMWFactory : CarFactory
{
//实现父类的抽象方法
public override ICar CarCreate()
{
//CarCreate方法,它就是实例化个宝马类,也就是子类决定实例化哪一个类.类的实例延迟到子类.
return new BMW();
}
}
//奔驰工厂,同宝马工厂
class BenzFactory : CarFactory
{
public override ICar CarCreate()
{
return new Benz();
}
}
}
运行结果:
如果要增加一个奥迪,要增加一个奥迪类,一个奥迪工厂类。
//增加一个奥迪
class AUDI : ICar
{
public void Show()
{
Console.WriteLine("四环奥迪就是我!!!");
}
}
//增加的奥迪工厂,同宝马工厂
class AUDIFactory : CarFactory
{
public override ICar CarCreate()
{
return new AUDI();
}
}
//增加的客户端代码
CarFactory audiFactory = new AUDIFactory();
ICar audi = audiFactory.CarCreate();
audi.Show();
运行结果:
完美的遵循了开发-封闭原则,对扩展开放,对修改关闭。而且每个类的职责都不多。
百度百科介绍:
工厂方法经常用在以下两种情况中:
第一种情况是对于某个产品,调用者清楚地知道应该使用哪个具体工厂服务,实例化该具体工厂,生产出具体的产品来。Java Collection中的iterator()方法即属于这种情况。
第二种情况,只是需要一种产品,而不想知道也不需要知道究竟是哪个工厂为生产的,即最终选用哪个具体工厂的决定权在生产者一方,它们根据当前系统的情况来实例化一个具体的工厂返回给使用者,而这个决策过程这对于使用者来说是透明的。