简单工厂模式(Simple Factory Pattern)
简单工厂模式是最简单的设计模式之一,它不属于GoF的23种设计模式,但应用也十分频繁,学习它是学习其他创建型模式的基础。在简单工厂模式中只需要记住一个简单的参数即可获得所需的对象实例,它提供专门的核心工厂类来负责对象的创建,实现对象创建和使用的分离。
简单工厂模式概述
例如用户要使用家具(Product),而用户并不需要考虑如何创建(生产)家具,用户只需要告诉家具工厂(Factory)需要什么家具(沙发、椅子、餐桌),由家具工厂来为用户创建(生产)家具,用户只需要使用家具就可以了,无需考虑家具的生产细节。家具的名称被称为参数,工厂可以根据参数的不同返回不同的产品,这就是简单工厂模式的动机。
其基本实现流程:首先将需要创建的各种不同产品对象的相关代码封装到不同的类中,这些类称为具体产品类,而将它们公共的代码进行抽象和提取后封装在一个抽象产品类中,每一个具体产品类都是抽象产品类的子类;然后提供一个工厂类用于创建各种产品,在工厂类中提供一个创建产品的工厂方法,该方法可以根据所传入的参数不同创建不同的具体产品对象;客户端只需调用工厂类的工厂方法并传入相应的参数即可得到一个产品对象。
定义:定义一个工厂类,它可以根据参数的不同返回不同类的实例,被创建的实例通常都具有共同的父类。
由于在简单工厂模式中用于创建实例的方法通常是静态(static)方法,因此简单工厂模式又被称为静态工厂方法(Static Factory Method)模式,它是一种类创建型模式。
简单工厂模式结构与实现
简单工厂模式结构
结构如图:
由图可知,简单工厂模式包含以下3个角色:
- Factory(工厂角色):即工厂类,该模式的核心,负责实现创建所有产品实例的内部逻辑。
- Product(抽象产品角色):工厂类创建的所有对象的父类。
- ConcreteProduct(具体产品角色):简单工厂模式的创建目标。
简单工厂模式实现
在简单工厂模式中客户端通过工厂类来创建一个产品类的实例,而无需直接使用new关键字来创建对象,它是工厂模式家族中最简单的一员。
在使用简单工厂模式时首先需要对产品类进行重构,不能设计一个包罗万象的产品类,而需根据实际情况设计一个产品层次结构,将所有产品类公共的代码移至抽象产品类,并在抽象产品类中声明一些抽象方法,以供不同的具体产品类来实现。典型的抽象产品类代码如下:
public abstract class Product {
//所有产品类的公共业务方法
public void methodSame() {
//公共方法的实现
}
//声明抽象业务方法
public abstract void methodDiff();
}
在具体产品类中实现了抽象产品类中声明的抽象业务方法,不同的具体产品类可以提供不同的实现。典型的具体产品类的代码如下:
public class ConcreteProduct extends Product {
//实现业务方法
public void methodDiff() {
//业务方法的实现
}
}
简单工厂模式的核心是工厂类,在没有工厂类之前客户端一般会使用new关键字创建产品对象,而引入工厂类之后客户端可以通过工厂类来创建产品,在简单工厂模式中工厂类提供了一个静态工厂方法供客户端使用,根据所传入的参数不同可以创建不同的产品对象。典型的工厂类的代码如下:
public class Factory {
//静态工厂方法
public static Product getProduct(String arg) {
Product product = null;
if(arg.equalsIgnoreCase("A")) {
product = new ConcreteProductA();
//初始化设置product
} else if(arg.equalsIgnoreCase("B")) {
product = new ConcreteProductB();
//初始化设置product
}
return product;
}
}
客户端代码中,通过调用工厂类的静态工厂方法得到产品对象。典型代码如下:
public class Client {
public static void main(String args[]) {
Product product;
product = Factory.getProduct("A");//通过工厂类创建产品对象
product.methodSame();
product.methodDiff();
}
}
简单工厂模式的简化
有时为了简化简单工厂模式,可以将抽象产品类和工厂类合并,将静态工厂方法移至抽象产品类中,如下图:
在上图中,客户端可以通过调用产品父类的静态工厂方法,根据参数的不同创建不同类型的产品子类对象,这种做法在很多类库和框架中也广泛存在。
简单工厂模式优/缺点与适用环境
优点:
- 实现了对象创建和使用的分离。
- 使用者只需要知道具体产品类对应的参数即可,一定程度上减少使用者的记忆量。
- 通过引入配置文件,可以在不修改任何客户端代码的情况下更换和增加新的具体产品类,在一定程度上提高了系统的灵活性。
缺点:
- 工厂类集中了所有具体产品类的创建逻辑,职责过重,一旦不能正常工作,整个系统都要受到影响。
- 增加了系统中类的个数,增加了系统的复杂度和理解难度。
- 系统扩展困难,一旦添加新产品就不得不修改工厂逻辑,在产品类型较多时有可能造成工厂逻辑过于复杂,不利于系统的扩展和维护。
- 简单工厂模式由于使用了静态工厂方法,造成工厂角色无法形成基于继承的等级结构。
简单工厂模式适用环境:
- 工厂类负责创建的对象比较少,由于创建的对象较少,不会造成工厂方法中的业务逻辑太过复杂。
- 客户端只知道传入工厂类的参数,对于如何创建对象并不关心。