静态工厂方法-Static Factory Method
·
文章目录
前言
系统总结一下静态工厂方法(Static Factory Method) 的特点:
📋 一、什么是静态工厂方法?
定义
用静态方法返回类的实例,代替直接调用构造器。
格式
public class Xxx {
public static Xxx of(...) { // 方法名常见有:of, create, getInstance, newInstance
return new Xxx(...);
}
}
🎯 二、核心特点(优点为主)
✅ 特点1:有意义的方法名
| 对比 | 表达含义 |
|---|---|
new User(1) |
只知道创建对象 |
User.of(1) |
表达“创建一个ID为1的用户” |
User.create(1) |
表达“创建一个用户” |
例子:
// 比 new ArrayList<>(10) 更语义化
List<String> list = List.of("a", "b", "c");
✅ 特点2:不必每次创建新对象(可缓存)
构造器每次都 new,但静态工厂可以复用已有对象:
// Boolean.valueOf() 就是这么做的
Boolean.valueOf(true); // ← 返回缓存的 Boolean.TRUE,不是每次 new
// 我们自己也可以这么设计
public class TemplateDataItem {
private static final Map<String, TemplateDataItem> CACHE = new HashMap<>();
public static TemplateDataItem of(String value) {
return CACHE.computeIfAbsent(value, v -> new TemplateDataItem(v, "#173177"));
}
}
✅ 特点3:可以返回子类型
构造器只能返回自身类型,静态工厂可以返回任意子类型(体现多态):
// 例子:可以返回不同实现
public class MessageSender {
public static MessageSender create(String type) {
if ("wechat".equals(type)) {
return new WeChatSender(); // 子类
} else if ("sms".equals(type)) {
return new SmsSender(); // 子类
}
return new MessageSender();
}
}
✅ 特点4:参数化创建更灵活
可以通过静态工厂方法名表达不同的创建方式:
// 多个工厂方法,表达不同的含义
public class TemplateDataItem {
// 用默认颜色
public static TemplateDataItem withDefaultColor(String value) {
return new TemplateDataItem(value, "#173177");
}
// 用红色
public static TemplateDataItem inRed(String value) {
return new TemplateDataItem(value, "#FF0000");
}
// 用自定义颜色
public static TemplateDataItem custom(String value, String color) {
return new TemplateDataItem(value, color);
}
}
✅ 特点5:提供默认值
就像我们项目里那样,工厂方法可以内置默认值,简化调用:
// 工厂方法内置默认颜色,调用者不用传
public static TemplateDataItem of(String value) {
return new TemplateDataItem(value, "#173177");
}
❌ 三、静态工厂方法的缺点
缺点1:无法被子类继承(如果构造器私有)
如果把构造器设为 private 而只留静态工厂,这个类就不能被继承了:
public class TemplateDataItem {
private TemplateDataItem() {} // 私有构造器,无法继承
}
缺点2:不像构造器那么直观
静态工厂方法名可能没有统一规范(有人用 of(),有人用 create()),不如构造器一眼就能识别。
📊 四、总结对比
| 特性 | 构造器 | 静态工厂方法 |
|---|---|---|
| 表达含义 | ⭐⭐ | ⭐⭐⭐⭐⭐ |
| 缓存对象 | ❌ 不行 | ✅ 可以 |
| 返回子类型 | ❌ 不行 | ✅ 可以 |
| 提供默认值 | ⚠️ 复杂 | ✅ 简单 |
| 可继承 | ✅ 可以 | ⚠️ 取决于构造器可见性 |
| 直观度 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ |
💡 五、最佳实践
常用的方法名规范
| 方法名 | 含义 | 例子 |
|---|---|---|
of |
“含有”、“使用” | List.of("a", "b") |
from |
从其他类型转换而来 | Date.from(instant) |
valueOf |
值转换 | Integer.valueOf("123") |
getInstance |
获取实例(可能单例) | Calendar.getInstance() |
create |
创建新实例 | Files.createPath(...) |
🎯 六、我们项目里的体现
@Data
public class TemplateDataItem {
private String value;
private String color;
// 体现了:提供默认值、表达含义清晰、代码简洁
public static TemplateDataItem of(String value) {
return new TemplateDataItem(value, "#173177");
}
// 体现了:灵活参数配置
public static TemplateDataItem of(String value, String color) {
return new TemplateDataItem(value, color);
}
}
TemplateDataItem.of() 这种 静态工厂方法(Static Factory Method) 的设计有很多好处,让我结合项目实际代码来解释:
📋 一、TemplateDataItem 的设计回顾
先看我们的代码:
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class TemplateDataItem {
private String value;
private String color;
// 静态工厂方法1:只传 value,颜色用默认值
public static TemplateDataItem of(String value) {
return new TemplateDataItem(value, "#173177");
}
// 静态工厂方法2:自定义 value 和 color
public static TemplateDataItem of(String value, String color) {
return new TemplateDataItem(value, color);
}
}
🎯 二、使用对比
不用静态工厂方法的写法(原始)
// 方式1:构造器
TemplateDataItem item1 = new TemplateDataItem();
item1.setValue("测试内容");
// 方式2:Builder(也还行,但更长)
TemplateDataItem item2 = TemplateDataItem.builder()
.value("测试内容")
.color("#173177")
.build();
// 方式3:全参数构造器
TemplateDataItem item3 = new TemplateDataItem("测试内容", "#173177");
用静态工厂方法的写法(简洁)
// 简洁!
TemplateDataItem item1 = TemplateDataItem.of("测试内容");
TemplateDataItem item2 = TemplateDataItem.of("测试内容", "#FF0000");
💡 三、设计好处详解
好处1:有意义的方法名 ✅
| 写法 | 表达意思 |
|---|---|
new TemplateDataItem(...) |
只是“创建对象” |
TemplateDataItem.of(...) |
“创建一个模板数据项” |
更符合业务语义!
好处2:提供默认值 ✅
这是我们项目里最实用的一点:
// 用静态工厂,不用每次都写默认颜色!
TemplateDataItem.of("测试内容")
// ↓ 等价于(帮你省去写默认值的麻烦)
TemplateDataItem.of("测试内容", "#173177")
如果不用静态工厂,你每次都得:
// 每次都得写默认颜色,麻烦!
TemplateDataItem.builder()
.value("测试内容")
.color("#173177") // 每次都得写,容易忘
.build();
好处3:可以缓存对象(扩展用) ✅
虽然我们现在没缓存,但静态工厂方法为将来留了扩展空间:
// 假设我们想缓存常用的颜色
private static final Map<String, TemplateDataItem> CACHE = new HashMap<>();
public static TemplateDataItem of(String value) {
String key = value + "#173177";
if (CACHE.containsKey(key)) {
return CACHE.get(key); // 直接返回缓存
}
TemplateDataItem item = new TemplateDataItem(value, "#173177");
CACHE.put(key, item);
return item;
}
构造器做不到这个!构造器每次都是 new,无法缓存。
好处4:更简洁 ✅
对比一下:
| 写法 | 代码行数 |
|---|---|
| 静态工厂 | TemplateDataItem.of("...") → 1行 |
| Builder | 需要4行左右 |
| 构造器+setter | 需要3行左右 |
好处5:参数顺序更清晰 ✅
看这两个:
// 静态工厂方法名清楚地表达了参数含义
TemplateDataItem.of("测试内容", "#FF0000") // 一看就知道先value,后color
// 如果是构造器,参数多了就容易搞混
new TemplateDataItem("#FF0000", "测试内容") // 容易传反!
📊 四、我们项目里的实际体现
在 WxPushApplicationTests.java 里你可以看到:
Map<String, TemplateDataItem> data = new HashMap<>();
data.put("first", TemplateDataItem.of("你好,这是一条测试消息")); // 简洁!
data.put("keyword1", TemplateDataItem.of("测试内容1"));
data.put("keyword2", TemplateDataItem.of("测试内容2"));
data.put("remark", TemplateDataItem.of("感谢你的关注!"));
如果不用静态工厂,这几行代码会变得很长很啰嗦!
🎓 五、总结对比
| 特性 | 构造器 | Builder | 静态工厂方法 of() |
|---|---|---|---|
| 简洁性 | ⭐⭐⭐ | ⭐⭐ | ⭐⭐⭐⭐⭐ |
| 默认值支持 | ❌ | ⚠️ 需要指定 | ✅ 内置默认 |
| 业务语义 | 弱 | 弱 | 强(“创建一个…”) |
| 可扩展性 | 弱 | 中 | 强(缓存、子类) |
| 我们项目 | ❌ 没选 | ⚠️ 保留但主要用 of() | ✅ 首选 |
💡 六、最佳实践建议
这是一个非常经典的设计模式,很多知名库都在用:
// Java 本身就在用
List.of("a", "b", "c")
Optional.of("value")
// 其他库
Gson gson = new GsonBuilder().create(); // 不过这个用 Builder 也很合适
所以,TemplateDataItem.of() 这种设计在我们项目里非常合适! 😊
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)