23种设计模式-简单工厂模式
产生背景
- 为什么需要工厂
当我们需要使用一个对象时,通常只需要通过关键字 new ,就可以得到一个实例,为什么还需要通过简单工厂这么繁琐的方式创建对象呢?
假如一个对象的创建,不仅仅包含实例化本身,还需要做大量的初始化操作,如:根据Locale不同,加载不同的国际化文件,并设置其中的值; 如果这种对象在很多地方使用,那么大量相同且繁琐的处理逻辑,会扩散到项目各个地方;
以下代码模拟了一个农场,在这个农场中有两个工作组,分别根据农场主的要求分派不同的事情;
其中:如果分配的活是“耕田”,则由男人来干; 如果分配的是“织布”,则由女人来干;
代码如下:
public interface Person{
void doSomething();
}
public class Man implements Person{
void doSomething(){
// 耕田
}
}
public class Woman implements Person{
void doSomething(){
// 织布
}
}
pulic class Farm{
void workGroup1(String jobType){
Person p = null;
if("织布".equals(jobType)){
p = new Woman();
}else("耕田".equals(jobType)){
p = new Man();
}
p.doSomething();
...做一些工作组一的其它事情
}
------------------------------------------------------------
void workGroup2(String jobType){
Person p = null;
if("织布".equals(jobType)){
p = new Woman();
}else("耕田".equals(jobType)){
p = new Man();
}
p.doSomething();
...做一些工作组二的其它事情
}
}
从上面代码可知:创建Person的代码,需要经过一个简单的逻辑判断;虽然代码简单,但是 相同代码却“ 到处扩散”; 而且调用方使用起来 非常繁琐;
因此,如果能把这些分散且繁琐的代码抽像出来,也许使用起来会简单的多;
目的
主要目的:
- 简化使用
主要原因:
- 对象实例化非常复杂
- 对象实例化包含一定的判断逻辑 ,重复代码到处扩散
概念
- 概念:
- 简单工厂模式又叫做静态工厂方法,由一个工厂类,根据参数不同,选择创建出一系列对象中的某一个;
本质:与单例模式一样,更像一个工具类;只不过是一个可以创建多个对象的工具类;
原理
- 与单例模式的区别
上一节我们提到单例模式,单例模式可以创建对象,为什么还需要简单工厂模式?
要想明白其中的原因,首先来对比一下他们的区别;
单例模式 | 单例模式 | 简单工厂模式 |
---|---|---|
实现方式 | 静态方法 | 静态方法 |
对象种类 | 单一类 | 一个抽象接口对应的多个类 |
对象数量 | 永远只有一个对象 | 调用一次,则创建一个新对象 |
单例模式:只能生成一个类的一个对象;
但通常情况下,我们需要创建一个抽象接口的不同实现的多个对象;此时就可以使用简单工厂模式
以上面代码为例,进行改造如下:
public class PersonFactory{
public static Person createPerson(){
Person p = null;
if("织布".equals(jobType)){
p = new Woman();
}else("耕田".equals(jobType)){
p = new Man();
}
return p ;
}
}
------------------------------------------------------------
pulic class Farm{
void workGroup1(String jobType){
//农场不需要关心如何创建,只需要有一个能干当前活的人就可以
Person p = PersonFactory.createPerson(jobType);
p.doSomething();
...做一些工作组一的其它事情
}
void workGroup2(String jobType){
Person p = PersonFactory.createPerson(jobType);
p.doSomething();
...做一些工作组一的其它事情
}
原理:
- 把分散的逻辑抽像到一个静态方法
- 根据条件判断,创建不同的对象
类图:
使用场景
当需要根据一定的逻辑,创建一个抽象接口的一系统对象时;
前提条件:抽象接口的实现类不应太多,而且种类固定(不会随着时间变化而增加),否则,简单工厂方法中的if else判断会越来越多,越来越复杂;而且还需要不断修改工厂方法,这违背了“开闭原则”;
实际案例
jdk中的NumberFormat
根据Local,返回适合当地类型的NumberFormat对象;
private static NumberFormat getInstance(Locale desiredLocale,
int choice);