简单工厂模式缺陷
大白话简单工厂模式(Simple Factory Pattern)中通过买车的经历解释了简单工厂模式。但熟悉设计模式的朋友会发现一些问题。
- 工厂类集中了所有实例(产品)的创建逻辑,一旦这个工厂不能正常工作,整个系统都会受到影响。用日产车工厂的例子来形容就是日产汽车的工厂负责所有车型的制造,当发生停电、火灾等情况时,汽车无法正常制造,大大影响汽车的销售,使企业陷入困境
- 违背“开放 - 关闭原则”,一旦添加新产品就不得不修改工厂类的逻辑,这样就会造成工厂逻辑过于复杂。这句话的意思是当企业发布新产品,该工厂需要重新学习新车型的制造,加大工人压力。
所以,随着企业的发展,日产公司决定将每种车型进行分工厂制造,解决了上述问题。这种方法在设计模式中被称为工厂方法模式
简单工厂模式改造
下面我们从代码的角度进行分析。4S店卖车首先要有车,这里只取日产部分车型逍客,轩逸和天籁。
代码片段1 日产车父类,所有车型都继承此类。
/**
* 日产车
* @author coderzcr
*/
abstract class NissanCar {
String name;
void printCar(){
System.out.println(name+"汽车已制造完成");
}
}
代码片段2 车型:逍客
/**
* 车型:逍客
* @author coderzcr
*/
class Xtrail extends NissanCar {
Xtrail(){
this.name = "逍客";
}
}
代码片段3 车型:轩逸
/**
* 车型:轩逸
* @author coderzcr
*/
class Sylphy extends NissanCar {
Sylphy(){
this.name = "轩逸";
}
}
代码片段4 车型:天籁
/**
* 车型:天籁
* @author coderzcr
*/
class Altima extends NissanCar {
Altima(){
this.name="天籁";
}
}
有了具体的车型要求,我们需要对不同车型建立工厂。
代码片段5 日产工厂父类,所有工厂都继承此类。
/**
* 日产车工厂
* @author coderzcr
*/
public abstract class NissanCarFactory {
/**
* 生产汽车
*/
abstract NissanCar createCar() ;
}
代码片段6 天籁工厂。
/**
* 天籁工厂
* @author coderzcr
*/
public class AltimaFactory extends NissanCarFactory {
@Override
NissanCar createCar() {
return new Altima();
}
}
代码片段7 逍客工厂。
/**
* 逍客工厂
* @author coderzcr
*/
public class XtrailFactory extends NissanCarFactory {
@Override
NissanCar createCar() {
return new Xtrail();
}
}
代码片段8 轩逸工厂。
/**
* 轩逸工厂
* @author coderzcr
*/
public class SylphyFactory extends NissanCarFactory {
@Override
NissanCar createCar() {
return new Sylphy();
}
}
图1 多工厂类图
工厂方法模式定义
工厂方法模式(Factory Method Pattern)又称为工厂模式,也叫虚拟构造器(Virtual Constructor)模式或者多态工厂(Polymorphic Factory)模式,它属于类创建型模式。在工厂方法模式中,工厂父类负责定义创建产品对象的公共接口,而工厂子类则负责生成具体的产品对象,这样做的目的是将产品类的实例化操作延迟到工厂子类中完成,即通过工厂子类来确定究竟应该实例化哪一个具体产品类。
工厂父类(日产车工厂)
工厂子类(轩逸工厂、天籁工厂、逍客工厂)
即产品的制造分配给子工厂,缓解单一工厂的压力。
工厂方法模式结构
图2 工厂方法模式结构
工厂方法模式包含如下角色:
- Product:抽象产品
- ConcreteProduct:具体产品
- Factory:抽象工厂
- ConcreteFactory:具体工厂
工厂方法模式分析
优点分析
- 工厂方法模式的优点包括简单工厂方法模式的优点:用户只需要关心所需产品对应的工厂,无须关心创建细节,甚至无须知道具体产品类的类名。
- 而且解决了简单工厂存在的不符合开闭原则问题,
在系统中加入新产品时,无须修改抽象工厂和抽象产品提供的接口,无须修改客户端,也无须修改其他的具体工厂和具体产品,而只要添加一个具体工厂和具体产品就可以了。这样,系统的可扩展性也就变得非常好,完全符合“开闭原则”。
缺点分析
添加新产品时,需要添加一个具体工厂和具体产品,在一定程度上增加了系统的复杂度,有更多的类需要编译和运行,会给系统带来一些额外的开销。