设计模式之简单工厂模式
简单工厂模式又叫做静态工厂方法模式,但不属于23种GOF设计模式,由于它太常用,因而将其放在首位,与后续的设计模式学习节奏保持一致。
一、模式实现
简单工厂将new对象的职责迁移到工厂中进行,通过传递的参数,在工厂中创建不同的实例化对象。下面通过具体的代码示例进行说明。
问题:某公司有一种产品,现有AB两种生产方式,现要求对其创建逻辑进行实现,并将具体的创建产品逻辑进行隔离。
现考虑用简单工厂模式的方法进行实现。
两种创建方式的功能实现代码如下:
public interface Product {
public void operator1();
public void operator2();
}
public class CreatProductA implements Product {
@Override
public void operator1() {
System.out.println("A产品进行1操作");
}
@Override
public void operator2() {
System.out.println("A产品进行2操作");
}
}
public class CreatProductB implements Product {
@Override
public void operator1() {
System.out.println("B产品进行1操作");
}
@Override
public void operator2() {
System.out.println("B产品进行2操作");
}
}
下面为简单工厂类的代码实现:
public class SimpleFactory {
public static Product creatProduct(String type) {
Product product = null;
if ("A".equals(type)) {
product = new CreatProductA();
} else if ("B".equals(type)) {
product = new CreatProductB();
}
return product;
}
}
下面为客户端调用的代码:
public class Client {
public static void main(String[] args) {
Product productA = SimpleFactory.creatProduct("A");
Product productB = SimpleFactory.creatProduct("B");
}
}
SimpleFactory通过Client中传递的参数type创建不同的Product实例对象。
如下简单工厂的类图:
注意:
1、简单工厂可用来创建接口、抽象类及普通类的实例。
2、在使用简单工厂的过程中通常没有创建工厂类实例的必要,因而常将简单工厂的方法写为静态的,故又静态工厂。
3、一般应将简单工厂的创建范围控制在独立组件或模块级别,避免工厂职责混淆。
简单工厂模式调用的时序图如下:
二、模式说明
简单工厂的本质是:选择实现,简单工厂用于为客户端选择相应的实现,可通过传递参数选择适当的实现类创建实例对象。选择方式主要有以下几种:
- 来自客户端。由客户端选择的参数选择
- 来自配置文件,从配置文件获取参数进行选择
- 来源于程序,通过运行期间产生的值进行选择
1、客户端传参
通过客户端参数选择如下:
public class Factory {
public static Api creatApi(int type) {
Api api = null;
if (type == 1) {
api = new ApiImpl1();
} else if (type == 2) {
api = new ApiImpl2();
}
return api;
}
}
其中creatApi方法中根据传入的type值,创建不同的Api对象。
缺点:客户端需理解传入的type值的含义,一定程度上暴露了代码的内部实现细节
2、配置文件传参
若添加新的创建API方法,则每次要修改工厂类,因而考虑其他实现工厂的方式,可通过配置文件的方式进行。
一般开发中采用properties文件或xml文件方式进行配置:
ApiImpl=com.luis.service.impl.ApiImpl3
此时工厂的代码如下:
public class Factory {
public static Api creatApi() {
Properties p = new Properties();
InputStream is = null;
try {
is = Factory.class.getResourceAsStream("ApiFactory.properties");
p.load(is);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
Api api = null;
try {
api = (Api) Class.forName(p.getProperty("ApiImpl")).newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return api;
}
}
可通过配置文件实现简单工厂创建不同的实例化对象。
三、模式总结
1、使用场景
-
需要完全封装隔离具体实现,外部只通过接口访问封装体,无需关心具体实现
-
将创建对象的职责集中管理控制
2、模式优缺点
优点:
- 帮助封装,真正实现面向接口编程。
- 解耦,通过简单工厂实现客户端与具体实现类的解耦。
- 简单工厂可通过一个含参的工厂方法,实例化任何产品类,戏称“上帝类”。
缺点:
- 增加客户端复杂度。通过客户端传参数在工厂中进行创建,增加客户端使用难度,暴露了内部实现。
- 子工厂难扩展。私有化简单工厂的构造方法,使用静态方法创建接口,不方便子工厂的扩展。
- 当所要生产产品种类非常多时,工厂方法的代码量可能会很庞大。
- 在遵循开闭原则(对拓展开放,对修改关闭)的条件下,简单工厂对于增加新的产品,只能通过修改工厂方法来实现。
参考:文章主要参考《研磨设计模式》一书