什么时候需要
- 根据参数不同创建同一父类下不同子类
- 将对象的创建与对象的使用分离,比如service负责使用dao,而不应该负责创建dao;否则,同一个dao的创建会出现在很多service,一旦需要修改,不仅违背开闭原则,而且改动面很大
模式结构
- 抽象产品角色:Product
- 具体产品角色:ConcreteProduct
- 工厂角色:Factory
模式实现
interface Product {
void otherMethods();
}
class ConcreteProductA implements Product {
public static final String NAME = "ConcreteProductA";
@Override
public void otherMethods() {
// do something
}
}
class ConcreteProductB implements Product {
public static final String NAME = "ConcreteProductB";
@Override
public void otherMethods() {
// do something
}
}
class Factory {
public static Product getProduct(String productName) {
if (ConcreteProductA.NAME.equals(productName)) {
return new ConcreteProductA();
} else if (ConcreteProductB.NAME.equals(productName)) {
return new ConcreteProductB();
} else {
throw new IllegalArgumentException("Not supported product name:" + productName);
}
}
}
- 工厂的方法是静态的,因此也叫静态工厂方法模式
- 不属于GoF23设计模式
- Simple Factory Pattern:定义一个工厂类,它可以根据参数的不同返回不同的实例,被创建的实例通常都具有共同的父类
- 用于创建的对象创建方式固定,改动小,比如只会通过new ConcreteProductA()创建
- 如果ConcreteProductA的创建有反射、new、不同构造器重载、cglib等多种形式,并且可能需要切换不同创建方式,那么建议使用工厂方法模式
优点
- 创建使用分离
- 客户端无需关系具体实现类,只需要具体实现的参数,如只需要知道传入参数ConcreteProductA,得到的是Product对象,而不用知道ConcreteProductA类
- 可以通过不同参数切换得到的不同Product实现
缺点
- 工厂类集中所有产品创建,职责过重,如一个工厂有几十个不同的工厂方法,用于创建几十个不同产品
- 增加类的个数
- 违背开闭原则,新增产品需要修改工厂类
- 使用静态工厂方法,工厂角色无法形成基于继承的等级结构