1. 定义
简单工厂模式(Simple Factory Pattern):定义一个工厂类,它可以根据参数的不同返回不同类的实例,被创建的实例通常都具有共同的父类。
工厂模式的作用,将实例的创建和使用进行分离,将实例化的配置和创建的过程封装在工厂类中。
简单工厂模式是工厂三兄弟之一,但并不属于 GOF 的 23 种设计模式。
使用的时候,无需关心实例化细节,只要传递自己想要的产品类型,创建过程委托给工厂来实现。
2. 设计
主要元素:
- 抽象产品。声明产品的属性和行为。
- 具体产品。抽象产品的实现。
- 具体工厂。负责产品的创建。
类图如下:
简单工厂模式-类图2.1. 普通简单工厂
一个工厂类,一个工厂方法,对传入的类型进行枚举,实例化产品。
public class NormalSimpleFactory {
public static final String TYPE_CHINESE = "Chinese";
public static final String TYPE_ENGLISH = "English";
public static final String TYPE_GERMAN = "German";
public IProduct getProduct(String type) {
if (TYPE_CHINESE.equals(type)) {
return new ChineseProduct();
} else if (TYPE_ENGLISH.equals(type)) {
return new EnglishProduct();
} else if (TYPE_GERMAN.equals(type)) {
return new GermanProduct();
} else {
return null;
}
}
}
虽然还是有 if else 对类型进行判断,但对于之前零散于各处的创建代码来说已经得到了很大的优化。
2.2. 多方法简单工厂
一个工厂类,多个工厂方法,无需枚举,每种方法返回对应的实例。
public class MultiMethodFactory {
public IProduct getChineseProduct() {
return new ChineseProduct();
}
public IProduct getEnglishProduct() {
return new EnglishProduct();
}
public IProduct getGermanProduct() {
return new GermanProduct();
}
}
可以不用去维护类型类表与类型和实例的关联管理。
2.3. 静态工厂方法(使用较多)
无需实例化工厂,调用方法直接为静态,所以也被称为 静态工厂方法。
public class StaticMethodSimpleFactory {
public static IProduct getChineseProduct() {
return new ChineseProduct();
}
public static IProduct getEnglishProduct() {
return new EnglishProduct();
}
public static IProduct getGermanProduct() {
return new GermanProduct();
}
}
3.应用
工厂模式用来就创建与使用解耦。工厂三兄弟有不同适用范围。
一般来说,简单会在几个情况下使用:
- 需要生产的产品比较简单,数量较少(因为简单工厂把所有产品创建集中起来,多了就复杂了)。
- 使用者无需记住创建细节,只要告诉工厂需要的类型。
3.1. JDK:MessageDigest
进行消息摘要的工具
MD2
MessageDigest md=MessageDigest.getInstance("MD2");
MD5
MessageDigest md=MessageDigest.getInstance("MD5");
SHA
MessageDigest md = MessageDigest.getInstance("SHA");
3.2. JDK:Executors
静态工厂方法提供默认的线程池。
阿里开发手册已经不推荐使用,希望我们自己创建线程池,并约束好最大任务数或最大线程数。
这里仅仅作为一个举例。
缓存线程池:�
ExecutorService cacheThreadPool = Executors.newCachedThreadPool();
固定线程数线程池:
ExecutorService fixCacheThreadPool = Executors.newFixedThreadPool(10);
单线程线程池:
ExecutorService singleThreadPool = Executors.newSingleThreadExecutor();
定时执行任务线程池:
ScheduledExecutorService scheduleThreadPool = Executors.newScheduledThreadPool(4);
4. 特点
4.1. 优点
- 易于阅读:因为类型不一样,需要 if else 分支判断,过多的 if else 代码块会造成维护困难,集中在工厂有利于代码复用和可读性。
- 易于修改:调用者可以遵循依赖倒置原则,面向抽象编程。创建过程交给工厂实现,如果更换产品只需要调整工厂。
- 易于复用:如果对象创建需要大量复杂的配置和初始化操作,内聚到工厂进行复用。
4.2. 缺点
-
要修改工厂。如果要新增产品,还是要修改工厂,不符合开闭原则
优化思路
如果产品相当复杂的话,可以考虑改用工厂方法或抽象工厂
4.3. 注意事项
- 生成的产品要足够简单,然后业务逻辑不能太复杂。如果创建过程过于复杂的话,可以考虑用其他模式进行配合。
网友评论