前言

系统总结一下静态工厂方法(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() 这种设计在我们项目里非常合适! 😊

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐