C++避免代码重复:跨项目复用类并使用不同对象实例的最优方法
嘿,这个问题我太熟悉了——预处理器指令确实能临时解决问题,但绝对不是最佳实践,毕竟它是编译时硬编码的方式,灵活性差还不好维护。下面给你几个行业内常用的优雅方案,完全不需要依赖预处理器:
最佳实现方案
1. 构造函数依赖注入(最推荐)
这是最符合依赖倒置原则的做法,把需要替换的对象实例通过父类的构造函数传入,子类或者调用方可以自由传入不同的实例,完美实现跨项目复用。
举个C++的示例(其他语言思路一致):
// 可复用的基类(放在公共项目中) class BaseService { protected: SomeInterface* m_dependency; public: // 构造函数注入依赖接口 BaseService(SomeInterface* dependency) : m_dependency(dependency) {} // 基类封装的复用业务逻辑 void doWork() { m_dependency->execute(); } }; // 项目A中的子类(继承基类,传入项目专属实例) class ProjectAService : public BaseService { public: ProjectAService() : BaseService(new ProjectASpecificImpl()) {} }; // 项目B中的子类(传入另一个专属实例) class ProjectBService : public BaseService { public: ProjectBService() : BaseService(new ProjectBSpecificImpl()) {} };
这种方式完全解耦了基类和具体依赖,不同项目只需要实现SomeInterface的专属类,然后在子类构造时传入即可,而且非常方便单元测试(比如传入Mock对象)。
2. 模板方法模式 + 延迟实例化
如果不想在构造阶段传入依赖,也可以在基类中定义抽象方法,让子类负责创建具体的对象实例,基类只专注于复用业务逻辑:
class BaseService { protected: // 子类必须实现这个方法,返回自身需要的对象实例 virtual SomeInterface* createDependency() = 0; public: void doWork() { auto dependency = createDependency(); dependency->execute(); // 注意内存管理,推荐用智能指针替代裸指针 delete dependency; } }; class ProjectAService : public BaseService { protected: SomeInterface* createDependency() override { return new ProjectASpecificImpl(); } };
这种方式把对象创建的责任完全交给子类,基类的业务逻辑可以毫无改动地复用在不同项目中。
3. 策略模式(适合多场景行为替换)
如果需要替换的不只是单个对象,而是一整套业务行为,策略模式会是更合适的选择:
// 定义策略接口(公共项目中) class BusinessStrategy { public: virtual void execute() = 0; }; // 基类持有策略对象,封装复用逻辑 class BaseService { protected: BusinessStrategy* m_strategy; public: BaseService(BusinessStrategy* strategy) : m_strategy(strategy) {} void doWork() { m_strategy->execute(); } }; // 项目A的专属策略 class ProjectAStrategy : public BusinessStrategy { public: void execute() override { // 项目A的具体业务逻辑 } };
这种方式甚至支持运行时动态切换策略,灵活性远胜于预处理器指令。
为什么不推荐预处理器指令?
- 编译时绑定:无法在运行时切换实例,一旦编译完成就无法修改;
- 可读性差:宏定义散落在代码中,调试和维护都很困难;
- 违反开闭原则:修改依赖需要修改基类代码或宏定义,而不是通过扩展子类实现。
内容的提问来源于stack exchange,提问作者DavidGo
相关产品推荐
相关产品推荐

