工厂模式是否适用于创建依赖集合而非依赖注入?
工厂模式与替代依赖注入的设计方案
首先明确回答:工厂模式完全支持你这种“集中创建并持有所需依赖实例,替代各处注入”的思路,除此之外还有几个模式也能适配这个场景,下面我逐一拆解:
一、工厂模式的实现方式
你可以创建一个专门的工厂类,由它负责初始化、管理所有依赖对象的生命周期,其他业务组件只需要从工厂获取实例,不用在每个类的构造器或方法里接收注入。
举个简单的Java示例(其他语言逻辑通用):
// 定义依赖接口 interface DatabaseConnection { void connect(); } class MySQLConnection implements DatabaseConnection { @Override public void connect() { // 实现MySQL连接逻辑 } } // 依赖工厂 class DependencyFactory { // 持有依赖实例(可按需设置为单例或多实例) private static DatabaseConnection dbConnection; private static Logger logger; static { // 集中初始化所有依赖 dbConnection = new MySQLConnection(); logger = new FileLogger(); } // 对外提供获取依赖的方法 public static DatabaseConnection getDbConnection() { return dbConnection; } public static Logger getLogger() { return logger; } } // 业务类直接从工厂拿依赖,无需注入 class UserService { private DatabaseConnection dbConn; private Logger logger; public UserService() { this.dbConn = DependencyFactory.getDbConnection(); this.logger = DependencyFactory.getLogger(); } }
这种方式把依赖的创建逻辑收拢到工厂中,避免了在每个业务类里重复处理注入逻辑,适合依赖关系相对稳定的场景。
二、其他可选模式
1. 服务定位器模式
服务定位器和工厂模式类似,但它更像一个全局的“服务注册表”——你可以把所有依赖实例注册到定位器中,然后在任意地方通过定位器查找获取。它比工厂更灵活,支持动态注册和替换实例,但要注意:过度使用会导致依赖关系变得隐蔽,不利于单元测试(需要额外模拟定位器的返回结果)。
2. 单例模式
如果你的依赖对象是全局唯一的(比如数据库连接池、全局配置管理器),单例模式可以让类自己管理实例,业务类直接调用Singleton.getInstance()获取。但单例的局限性也很明显:它会让业务类和单例类强耦合,而且单例的生命周期很难控制,测试时替换实例比较麻烦。
三、方案选择的权衡
虽然这些模式能减少注入代码,但也要对比和依赖注入(DI)的差异:
- 依赖注入的优势是显式依赖,业务类的依赖一目了然,单元测试时可以轻松替换模拟对象,松耦合性更好;
- 工厂/服务定位器的优势是集中管理,适合小型项目或依赖关系简单的场景,但如果项目复杂度上升,可能会出现“依赖黑洞”——你很难快速追踪某个类到底依赖了哪些对象。
所以建议根据项目规模和复杂度选择:如果是小型项目,工厂模式完全够用;如果是大型项目,可以考虑结合DI框架和工厂模式,用工厂封装复杂的依赖创建逻辑,再通过DI注入工厂实例。
内容的提问来源于stack exchange,提问作者Dave Jones
相关产品推荐
相关产品推荐

