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”,而是让创建逻辑从业务逻辑中分离出来。

只要对象创建过程开始影响业务代码可读性,就应该考虑引入创建型模式。