工厂方法模式通过将构造函数设为private或package-private来收窄访问权限,再由public static工厂方法统一创建实例,从而杜绝外部直接new、保障封装性与控制逻辑(如校验、缓存、单例)。

工厂方法模式里,构造函数的访问权限不是靠“放开”来实现的,而是靠“收窄”来配合——把构造函数设为 private 或 package-private(默认),再把对象创建逻辑交给静态工厂方法。这是控制实例化入口、避免随意 new 的核心手段。
为什么构造函数必须私有或受限?
工厂方法的本质是将对象创建过程集中管理。如果构造函数是 public,外部代码就能绕过工厂直接 new 实例,破坏封装、导致状态不一致,也使单例、缓存、参数校验等逻辑失效。
- private 构造函数:彻底禁止外部调用,连同包类、子类都不能 new,只允许本类的静态方法(如 getInstance())内部调用
- package-private(无修饰符):适合模块内协作场景,同一包下的工厂类可调用,但跨包不可见,比 private 更灵活一点
- protected 构造函数:极少用于标准工厂方法,更适合抽象父类供子类继承扩展,不属于典型工厂模式做法
工厂类如何配合受限构造函数?
静态工厂方法本身是 public 的,它在类内部调用私有构造函数完成初始化,再返回实例。这个过程对外隐藏了构造细节,只暴露可控的创建接口。
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- 方法命名更语义化:比如 valueOf()、of()、getInstance()、newBuilder(),比 new 更易懂
- 可返回缓存对象、子类实例或 null(如 Optional.empty()),构造函数做不到
- 可做参数预处理或合法性检查,失败时抛异常或返回空,避免构造出非法对象
常见误用与规避建议
新手常犯两类错误:一是构造函数留 public 却又写工厂方法,造成双入口;二是把工厂方法也设成 private,导致无法调用。
- 确保工厂方法是 public static,且构造函数不是 public
- 不要在工厂方法里调用 super() 或 this()——那是构造器链,工厂方法是独立入口
- 若需支持子类定制创建逻辑,应使用模板方法模式(定义 abstract factory 方法),而非开放构造函数
一个简洁示例
以下是一个典型的私有构造 + 静态工厂写法:
class Connection {private final String url;
private Connection(String url) {
if (url == null || url.trim().isEmpty()) throw new IllegalArgumentException();
this.url = url;
}
public static Connection of(String url) {
return new Connection(url);
}
}
外部只能通过 Connection.of("jdbc:...") 获取实例,无法 new Connection(...) —— 权限控制和业务约束都落到了实处。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










