工厂模式概述
意义
- 问题引出
在面向对象编程中, 最通常的方法是一个new操作符产生一个对象实例,new操作符就是用来构造对象实例的。当我们使用 new 来构造一个新的类实例时,其实是告诉了 JVM 我需要一个新的实例。JVM 就会自动在内存中开辟一片空间,然后调用构造函数来初始化成员变量,最终把引用返回给调用方。
但是在一些情况下, new操作符直接生成对象会带来一些问题。举例来说, 许多类型对象的创造需要一系列的步骤: 你可能需要计算或取得对象的初始设置; 选择生成哪个子对象实例; 或在生成你需要的对象之前必须先生成一些辅助功能的对象。在这些情况,新对象的建立就是一个 “过程”,不仅是一个操作,像一部大机器中的一个齿轮传动。 - 解决的问题
如何能轻松方便地构造对象实例,而不必关心构造对象实例的细节和复杂过程呢? 一个核心思想
在所有的工厂模式中,两个类A和B之间的关系应该仅仅是A创建B或是A使用B,而不能两种关系都有。
将对象的创建和使用分离,也使得系统更加符合“单一职责原则”,有利于对功能的复用和系统的维护。概念
GOF为工厂模式的定义:
“Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses.”
在基类中定义创建对象的一个接口,让子类决定实例化哪个类。工厂方法让一个类的实例化延迟到子类中进行。用工厂方法代替new操作来实例化对象
- 定义一个接口来创建对象,但是让子类来决定哪些类需要被实例化
适用场合
- 有一组类似的对象需要创建。
- 在编码时不能预见需要创建哪些种类的实例。
- 系统需要考虑扩展性,不应依赖于产品类实例如何被创建、组合和表达的细节。
分类
- 简单工厂(Simple Factory)模式,又称静态工厂方法模式(Static Factory Method Pattern)。
- 工厂方法(Factory Method)模式,又称多态性工厂(Polymorphic Factory)模式或虚拟构造子(Virtual Constructor)模式;
- 抽象工厂(Abstract Factory)模式,又称工具箱(Kit 或Toolkit)模式。
联系
这三种模式从上到下逐步抽象,并且更具一般性。
GOF在《设计模式》一书中将工厂模式分为两类:工厂方法模式(Factory Method)与抽象工厂模式(Abstract Factory)。
将简单工厂模式(Simple Factory)看为工厂方法模式的一种特例,两者归为一类。区别
工厂方法模式:
一个抽象产品类,可以派生出多个具体产品类。
一个抽象工厂类,可以派生出多个具体工厂类。
每个具体工厂类只能创建一个具体产品类的实例。
抽象工厂模式:
多个抽象产品类,每个抽象产品类可以派生出多个具体产品类。
一个抽象工厂类,可以派生出多个具体工厂类。
每个具体工厂类可以创建多个具体产品类的实例。
简单工厂模式
定义
定义一个工厂类,可以根据参数的不同返回不同类的实例。简单工厂模式专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。因为在简单工厂模式中用于创建实例的方法是静态(static)方法,因此简单工厂模式又被称为静态工厂方法(Static Factory Method)模式,它属于类创建型模式。
地位
简单工厂模式并不是23种常用的设计模式之一,它只算工厂模式的一个特殊实现。简单工厂模式在实际中的应用相对于其他2个工厂模式用的还是相对少得多,因为它只适应很多简单的情况。违背了我们在概述中说的 开放-封闭原则 ,每次要新添加一个功能,都需要在生switch-case 语句(或者if-else 语句)中去修改代码,添加分支条件。
角色
工厂类角色—Factory
- 工厂角色即工厂类,它是简单工厂模式的核心,负责实现创建所有产品实例的内部逻辑
- 工厂类可以被外界直接调用,创建所需的产品对象
抽象产品角色—Product
它是工厂类所创建的所有对象的父类,所创建的具体产品对象都是其子类对象具体产品角色—Concrete Product
工厂方法模式所创建的任何对象都是这个角色的实例
适用场合
- 在工厂类中提供一个创建产品的工厂方法,该方法可以根据所传入的参数不同创建不同的具体产品对象
- 客户端只需调用工厂类的工厂方法并传入相应的参数即可得到一个产品对象,而无须直接使用new关键字来创建对象。
一个例子
- 产品接口类:Product.java
1 | public interface Product { |
- 具体的产品类:Iphone.java
1 | public class Iphone implements Product { |
- 具体的产品类:Ipad.java
1 | public class Ipad implements Product { |
- 具体的产品类:Iwatch.java
1 | public class Iwatch implements Product { |
- 生产产品的工厂类 (简单的工厂类/静态工厂类):ProductFactory.java
1 | public class ProductFactory { |
- 客户端调用工厂类静态方法创建产品:Client.java
1 | public class Client { |
工厂方法模式
定义
工厂方法模式去掉了简单工厂模式中工厂方法的静态属性,使得它可以被子类继承。这样在简单工厂模式里集中在工厂方法上的压力可以由工厂方法模式里不同的工厂子类来分担。这样使得结构变得灵活起来——当有新的产品产生时,只要按照抽象产品角色、抽象工厂角色提供的合同来生成,那么就可以被客户使用,而不必去修改任何已有的代码。可以看出工厂角色的结构也是符合开闭原则的!
地位
工厂方法模式是对简单工厂模式的设计优化,简单工厂模式中如果新增一类产品类型时,需要修改工厂静态方法的产品创建逻辑,而使用工厂方法模式只需新扩展出一个新的工厂子类或是实现类来针对新增类型产品的创建工作、使系统具有了良好的扩展性与维护性
角色
抽象工厂角色— Factory
这是工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类
具体工厂角色— Concrete Factory
它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象
抽象产品角色—Product
它是具体产品继承的父类或者是实现的接口
具体产品角色—ConcreteProduct
具体工厂角色所创建的对象就是此角色的实例
适用场合
- 客户端不知道它所需要的对象的类。在工厂方法模式中,客户端不需要知道具体产品类的类名,只需要知道所对应的工厂即可,具体的产品对象由具体工厂类创建
- 抽象工厂类通过其子类来指定创建哪个对象。在工厂方法模式中,对于抽象工厂类只需要提供一个创建产品的接口,而由其子类来确定具体要创建的对象
一个例子
- 产品接口类:Product.java
1 | public interface Product { |
- 具体的产品类:Iphone.java
1 | public class Iphone implements Product { |
- 具体的产品类:Ipad.java
1 | public class Ipad implements Product { |
- 具体的产品类:Iwatch.java
1 | public class Iwatch implements Product { |
- 生产产品的工厂类 (简单的工厂类/静态工厂类):ProductFactory.java
1 | public class ProductFactory { |
- 客户端调用工厂类静态方法创建产品:Client.java
1 | public class Client { |
抽象工厂模式
参考文章
创建对象与使用对象——谈谈工厂的作用
深入理解工厂模式
JAVA设计模式之工厂模式(简单工厂模式+工厂方法模式)
关于 Java 的静态工厂方法,看这一篇就够了!
JAVA设计模式之 简单工厂模式【Simple Factory Pattern】