设计模式01-工厂模式

在实际生活中,原始社会自给自足(没有工厂)→农耕社会小作坊(简单工厂)→工业革命以后的流水线(工厂方法)→现代产业链工厂(抽象工厂);项目代码同样也是由简至繁逐步迭代而来,创建者封装复杂的创建逻辑,简化调用者的调用逻辑。

简单工厂/静态工厂

模式定义

简单工厂模式(Simple Factory Pattern)是指由一个工厂对象决定创建出哪一种产品类的实例。简单工厂属于创建型模式,但不包含在GOF 23种设计模式之。

示例代码

以课程为例,代码类图

首先创建课程接口:

1
2
3
4
public interface ICourse {
//录制课程
void record();
}

然后分别创建JavaCourse、PythonCourse并实现ICourse接口:

1
2
3
4
5
6
public class JavaCourse implements ICourse {
@Override
public void record() {
System.out.println("JavaCourse");
}
}
1
2
3
4
5
6
public class PythonCourse implements ICourse {
@Override
public void record() {
System.out.println("PythonCourse");
}
}

再创建工厂类:

1
2
3
4
5
6
7
8
9
10
11
public class CourseFactory {
public ICourse create(Class clazz) {
if ("Java".equals(courseName)) {
return new JavaCourse();
} else if ("Python".equals(courseName)) {
return new PythonCourse();
} else {
return null;
}
}
}

客户端调用示例:

1
2
3
4
5
6
7
8
public class SimpleFactoryTest {
public static void main(String[] args) {
//封装创建逻辑,客户端只需要调用工厂类的方法即可,简化调用逻辑
CourseFactory factory = new CourseFactory();
ICourse course = factory.create("Java");
course.record();
}
}

当增加课程时,创建新课程类实现课程接口,客户端调用传入对应参数即可

JDK实例

  • Calendar.getInstance()

框架实例

  • LoggerFactory.getLogger()

适用场景

  • 主要用于简化客户端调用逻辑,封装创建细节
  • 工厂类负责创建的对象有限或较少
  • 客户端只需要传入工厂类的参数,对于如何创建对象的逻辑不需要关心

模式优点

  • 只需要传入一个正确的参数就可以获取所需要的对象,无须了解创建逻辑

模式缺点

  • 工厂类的职责过重,增加新的产品时需要修改工厂类的判断逻辑,违背开闭原则
  • 不易于扩展过于复杂的产品结构(一个创建类只能返回一个产品类)

工厂方法

模式定义

工厂方法模式(Factory Method Pattern)是指定义一个创建对象的接口,但让实现这个接口的类来决定实例化哪个类,工厂方法让类的实例化推迟到子类中进行。工厂方法属于创建型模式。

示例代码

工厂方法模式主要解决产品扩展的问题。在简单工厂中,随着产品链增加,工厂的职责会变得越来越多,不便于维护。因此,根据单一职责原则,将职能继续拆分,Java工厂创建Java课程,Python工厂创建Python课程,对工厂本身再做一层抽象。

先创建ICourseFactory接口:

1
2
3
public interface ICourseFactory {
ICourse create();
}

分别创建子工厂:

1
2
3
4
5
6
public class JavaCourseFactory implements ICourseFactory {
@Override
public ICourse create() {
return new JavaCourse();
}
}
1
2
3
4
5
6
public class PythonCourseFactory implements ICourseFactory {
@Override
public ICourse create() {
return new PythonCourse();
}
}

测试类:

1
2
3
4
5
6
7
8
9
10
11
public class FactoryMethodTest {
public static void main(String[] args) {
ICourseFactory javaCourseFactory = new JavaCourseFactory();
ICourse javaCourse = javaCourseFactory.create();
javaCourse.record();

ICourseFactory pythonCourseFactory = new PythonCourseFactory();
ICourse pythonCourse = pythonCourseFactory.create();
pythonCourse.record();
}
}

JDK实例

  • ArrayList里面的 iterator()

Spring实例

  • FactoryBean

适用场景

  • 创建对象时需要大量重复的代码
  • 客户端不依赖于产品类示例如何被创建、实现等细节
  • 一个类通过其子类来指定创建哪个对象

模式优点

  • 用户只需关心产品所对应的工厂,无须关心创建细节
  • 加入新产品符合开闭原则,提高了系统的可扩展性

模式缺点

  • 类的个数容易过多,增加了代码结构的复杂度
  • 增加了系统的抽象性和理解难度

抽象工厂

模式定义

抽象工厂模式(Abstract Factory Pattern)是指提供一个创建一系列相关或相互依赖对象的接口,无须指定他们具体的类。抽象工厂属于创建型模式。

示例代码类图

JDK实例

以iterator()为例:

工厂关系:Collection→List→ArrayList

产品关系:Iterator→ListIterator→ArrayListIterator

Spring实例

  • AbstractFactoryBean

适用场景

  • 客户端不依赖于产品类实例如何被创建、实现等细节
  • 强调一系列相关的产品对象(同一产品族)一起使用,创建对象需要大量重复的代码
  • 提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于具体实现

模式优点

  • 具体代码在应用层隔离,无须关心创建细节
  • 将一个系列的产品族统一到一起创建

模式缺点

  • 规定了所有可能被创建的产品集合,产品族中扩展新的产品困难,需要修改抽象工厂的接口
  • 增加了系统的抽象性和理解难度

总结

  • 简单工厂:主要解决产品创建问题,封装创建逻辑,一层封装
  • 工厂方法:主要解决产品扩展问题,封装一类产品的创建逻辑,两层封装
  • 抽象工厂:主要解决产品族与产品等级结构问题,封装不同族不同类的创建逻辑,三层封装

参考