一、介绍
工厂模式可以分为 3 个小类
- 简单工厂模式
- 工厂方法模式
- 抽象工厂模式
工厂模式的工厂类,并不一定以 Factory 结尾,例如 DataFormat、Calender 他们都是工厂类,通过静态方法来创建实例。
除此之外,创建对象的方法名称一般是 create+类名,但是也有其他的命名方式例如 getInstance()、createInstance() createInstance() ,甚至是 valueOf 也是工厂的方法例如 String 的 valueOf()方法。
二、简单工厂模式
介绍
- 将创建对象的函数,从代码中剥离并且将其放到一个独立的类中。让这个类只负责对象的创建。那这个类就是简单工厂模式的工厂类。
- 虽然大部分的工厂模式的结尾都是 Factory,但是不是必须的,例如 Java 中的 DateFormat、Calender 尽管没有以 Factory 但是他们也是工厂类。甚至 String.valueOf 也是工厂类。
自定义案例代码
// 定义 Shape 接口
interface Shape {
void draw();
}
// 具体形状类:圆形
class Circle implements Shape {
@Override
public void draw() {
System.out.println("Inside Circle::draw() method.");
}
}
// 具体形状类:矩形
class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("Inside Rectangle::draw() method.");
}
}
// 简单工厂类,用于创建形状对象
class ShapeFactory {
// 使用 getShape 方法获取形状类型的对象
public static Shape getShape(String shapeType) {
if (shapeType == null) {
return null;
}
else if (shapeType.equalsIgnoreCase("CIRCLE")) {
return new Circle();
}
else if (shapeType.equalsIgnoreCase("RECTANGLE")) {
return new Rectangle();
}
return null;
}
}
// 客户端代码
public class SimpleFactoryPatternDemo {
public static void main(String[] args) {
// 获取形状类型的对象
Shape shape1 = ShapeFactory.getShape("CIRCLE");
// 调用 Circle 的 draw 方法
shape1.draw();
Shape shape2 = ShapeFactory.getShape("RECTANGLE");
// 调用 Rectangle 的 draw 方法
shape2.draw();
// 请求一个不支持的形状类型
Shape shape3 = ShapeFactory.getShape("SQUARE");
if (shape3 != null) {
shape3.draw();
} else {
System.out.println("Shape not supported.");
}
}
}
第二类简单工厂
如果将简单工厂模式和类似的单例模式组合起来,那么可以称之为第二类简单工厂模式
public class ReleConfigParseFactory{
private static final Map<String,RuleConfigParse> rulesMap=new HashMap<>();
static{
rulesMap.put(XXXX)
}
public static getParse(String name){
return relesMap.get(name);
}
}
三、工厂方法模式
- 简单工厂模式如果要新增产品类型则需要在工厂类中新增 不够符合开闭原则
- 工厂方法模式 对于新增一个具体的产品来说,只需要新增一个工厂类更符合开闭原则。
- 在业务中创建工厂类仍然负责,所以可以结合简单工厂。对于具体的 FactoryABC 再创建一个简单工厂也就是工厂的工厂。这样新增工厂类后,只需要在工厂的工厂中添加该工厂而不需要大量的改动。
缺点:
- 工厂类只包含一个创建代码,功能单薄有点过度设计。如果代码足够简单,应该使用简单工厂模式。
四、抽象工厂模式
如果具体需要创建的对象包含多种分类,那么实用工厂方法模式可能会产生大量的工厂类。
例如上图,包含两种产品 Computer 和 Phone ,同事包含两个厂商 小米和苹果,如果使用工厂方法则会产生四个工厂。
引入抽象工厂模式后,AppleFactory 和 MiFactory 每个工厂负责多种类型的产品可以有效减少对应工厂的个数。
五、总结
使用工厂模式的场景
场景 1:代码中存在根据不同条件创建不同对象的代码,可以考虑使用工厂模式将这一大段代码进行抽离。如果每个对象的创建都比较简单那么就使用简单工厂模式,如果对象的创建过程比较负责责使用工厂方法模式将每个对象的创建过程封装到各自的工厂类中。
**场景 2:**一个类的对象创建比较复杂,例如涉及其他的对象,复杂的初始化逻辑等。也可以考虑使用工厂模式,将对象创建的过程封装到工厂模式中。
工厂模式作用总结:
可以根据下面四条规则判断是否使用工厂模式
- 封装变化 利用工厂模式封装创建逻辑,创建逻辑的变更对调用者透明。
- 代码复用 避免业务中创建对象的代码散落各处,避免重复编写。
- 隔离复杂性:封装复杂的创建逻辑,让使用者无需关注具体的创建细节。
- 控制复杂度:将创建逻辑与使用逻辑分离,简化代码。
开发中常见的工厂模式案例
- DateFormat、Calendar 类
- 日志工厂 LoggerFactory 经常使用工厂模式来创建日志记录器(Logger)实例。开发者可以通过工厂方法请求一个日志记录器,而不需要知道具体实现细节。这样可以在不修改应用程序代码的情况下,灵活切换日志框架。
- Spring 这种 DI 框架,例如 BeanFactory 管理着对象的声明周期,也作为对象的创建工厂