2026年7月11日 · 4 分钟阅读
Java 创建型设计模式:单例、工厂、原型与建造者
系统梳理创建型设计模式的使用场景、实现思路和 Java 项目中的落地规范。
创建型模式关注一个问题:对象应该由谁创建,以及创建过程如何从业务逻辑中隔离出来。
当对象创建逻辑很简单时,直接 new 没有问题。但当创建过程涉及配置、条件判断、缓存、复制、复杂参数组装时,就应该考虑创建型模式。
单例模式
单例模式保证一个类在系统中只有一个实例,并提供全局访问点。
典型场景:
- 配置中心。
- 日志组件。
- 线程池。
- 无状态工具服务。
线程安全的懒加载写法可以使用静态内部类:
public class ConfigCenter {
private ConfigCenter() {
}
private static class Holder {
private static final ConfigCenter INSTANCE = new ConfigCenter();
}
public static ConfigCenter getInstance() {
return Holder.INSTANCE;
}
}
这种方式利用类加载机制保证线程安全,同时做到延迟初始化。
单例模式使用规范
单例不要保存请求级状态。例如当前用户、当前订单、当前事务都不应该放在单例对象里。
判断一个类能不能做单例,可以问两个问题:
- 它是否无状态,或者状态是否全局共享?
- 多线程访问时是否安全?
如果答案不确定,就不要急着使用单例。
工厂模式
工厂模式用于隐藏对象创建细节,让调用方只关心要什么对象,而不关心怎么创建。
简单工厂示例:
public interface Notification {
void send(String message);
}
public class EmailNotification implements Notification {
public void send(String message) {
System.out.println("email: " + message);
}
}
public class SmsNotification implements Notification {
public void send(String message) {
System.out.println("sms: " + message);
}
}
public class NotificationFactory {
public static Notification create(String type) {
if ("email".equals(type)) {
return new EmailNotification();
}
if ("sms".equals(type)) {
return new SmsNotification();
}
throw new IllegalArgumentException("unsupported type");
}
}
简单工厂适合类型较少、变化不频繁的场景。
工厂方法
当创建逻辑本身也需要扩展时,可以使用工厂方法。
public interface NotificationFactory {
Notification create();
}
public class EmailFactory implements NotificationFactory {
public Notification create() {
return new EmailNotification();
}
}
新增一种通知方式时,新增工厂类和产品类即可,原有工厂不需要被频繁修改。
抽象工厂
抽象工厂用于创建一组相关对象。
例如不同平台的 UI 组件:
public interface UiFactory {
Button createButton();
Dialog createDialog();
}
如果产品族之间必须保持一致,例如 Windows 风格按钮搭配 Windows 风格弹窗,就适合抽象工厂。
原型模式
原型模式通过复制已有对象创建新对象。
它适合对象创建成本较高,或者对象初始状态复杂的场景。
public class ReportTemplate implements Cloneable {
private String title;
private List<String> sections;
@Override
public ReportTemplate clone() {
try {
ReportTemplate copy = (ReportTemplate) super.clone();
copy.sections = new ArrayList<>(this.sections);
return copy;
} catch (CloneNotSupportedException e) {
throw new AssertionError(e);
}
}
}
原型模式要重点区分浅拷贝和深拷贝。对象内部有集合、引用对象时,通常需要手动处理深拷贝,否则多个对象可能共享同一份可变数据。
建造者模式
建造者模式用于分步骤创建复杂对象,尤其适合参数很多、可选项很多的对象。
public class Article {
private final String title;
private final String content;
private final List<String> tags;
private Article(Builder builder) {
this.title = builder.title;
this.content = builder.content;
this.tags = builder.tags;
}
public static class Builder {
private String title;
private String content;
private List<String> tags = List.of();
public Builder title(String title) {
this.title = title;
return this;
}
public Builder content(String content) {
this.content = content;
return this;
}
public Builder tags(List<String> tags) {
this.tags = tags;
return this;
}
public Article build() {
return new Article(this);
}
}
}
建造者模式可以避免构造函数参数过长,也能让对象创建过程更清晰。
创建型模式选择建议
| 场景 | 推荐模式 |
|---|---|
| 全局唯一对象 | 单例 |
| 根据类型创建对象 | 简单工厂 |
| 创建逻辑需要扩展 | 工厂方法 |
| 创建一组相关对象 | 抽象工厂 |
| 复制复杂对象 | 原型 |
| 分步骤组装复杂对象 | 建造者 |
小结
创建型模式的核心不是“少写 new”,而是让创建逻辑从业务逻辑中分离出来。
只要对象创建过程开始影响业务代码可读性,就应该考虑引入创建型模式。