前面提到了简单工厂,由于简单工厂的缺点:违背开放-封闭原则和单个类(工厂类)职责过多,工厂方法是简单工厂的抽象,克服了简单工厂的缺点。
概念:
工厂方法模式(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()方法即属于这种情况。
第二种情况,只是需要一种产品,而不想知道也不需要知道究竟是哪个工厂为生产的,即最终选用哪个具体工厂的决定权在生产者一方,它们根据当前系统的情况来实例化一个具体的工厂返回给使用者,而这个决策过程这对于使用者来说是透明的。