概要
工厂模式是创建型模式:即用于创建对象。工厂模式一般细分为三种类型:简单工厂、工厂方法、抽象工厂。不过简单工厂可看成是工厂方法的一种特例。
原理就是这篇文章讲的:juejin.cn/post/716950…
其中代表性的就是下图:工厂方法将实例创建延迟到子类。
今天思考下,什么时候直接使用 new 创建对象,什么时候使用工厂方法?
简单工厂
如上图的左边部分:产品类有一个接口,有具体的实现。在工厂方法中写 if-else 嵌套。
基于这样的实现方式,当我们新建一个产品的时候。其实并不完全是符合开闭原则的。因为工厂方法中涉及到 if-else 判断,势必会改动这个这个类。但是如果不是需要频繁的添加产品类,那么也是可以接收的。
简单工厂模式:工厂类中有多处 if-else 实现,但是在不频繁添加 产品类的情况下是没有问题的
工厂方法
如上图的右边部分,更加符合开闭原则,新增一个产品类,只需要新增一个工厂实现类和具体产品实现类即可。再也没有多个 if-else 嵌套的情况了。
具体示例代码可参看:juejin.cn/post/716950…
什么时候用简单工厂或者工厂方法
一般来说,如果某个代码块逻辑过于复杂,那么我们需要抽出来独立为函数或则类,这样代码会更加清晰。如果就几行代码,就完全没必要拆分。
基于上面思想,当创建对象逻辑比较复杂的时候,比如需要组合其他对象,做各种初始化操作,推荐使用工厂方法模式「将实现逻辑推迟到具体的实现类」。其他一般情况就简单工厂,或者直接 new 。
抽象工厂
为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类。
也就是一个工厂负责创建多个不通类型的对象,这样可以有效减少工厂类的个数。
//产品类
public interface ProductA {
void methodA();
}
public interface ProductB {
void methodB();
}
public class ProductA1 implements ProductA {
@Override
public void methodA() {
System.out.println("A1");
}
}
public class ProductA2 implements ProductA {
@Override
public void methodA() {
System.out.println("A2");
}
}
public class ProductB1 implements ProductB {
@Override
public void methodB() {
System.out.println("B1");
}
}
public class ProductB2 implements ProductB {
@Override
public void methodB() {
System.out.println("B2");
}
}
//工厂类
public interface ProductFactory {
ProductA createA();
ProductB createB();
}
public class ProductFactoryA implements ProductFactory {
@Override
public ProductA createA() {
return new ProductA1();
}
@Override
public ProductB createB() {
return new ProductB1();
}
}
public class ProductFactoryB implements ProductFactory {
@Override
public ProductA createA() {
return new ProductA2();
}
@Override
public ProductB createB() {
return new ProductB2();
}
}
//测试
public class Test {
public static void main(String[] args) {
ProductFactory productFactory=new ProductFactoryA();
ProductA producta=productFactory.createA();
ProductB productb=productFactory.createB();
producta.methodA();
productb.methodB();
}
}
实际开发使用的工厂模式案例
- Java 中的 Calendar 、DateFormat、ValueOf()等
Calendar.getInstance();
DateFormat.getDateInstance();
String.valueOf("");
Integer.valueOf(10);
- Spring 中的 IOC:BeanFactory