整洁架构中为何使用抽象类?能否仅使用实现类?
在整洁架构里,先定义只含函数声明的抽象类、再编写实现类完成具体逻辑的做法,本质是为了解耦代码、提升可维护性和扩展性,具体来说有这几个关键原因:
1. 遵循依赖倒置,让高层逻辑不绑定底层细节
这是整洁架构的核心原则:高层业务模块应该依赖抽象接口,而非具体的实现类。比如你的业务层如果直接依赖PriceTrackerDataSourceImpl,哪天要把WebSocket换成HTTP轮询,就得修改业务层的代码;但如果依赖的是PriceTrackerDataSource这个抽象,只要新的实现类符合接口规范,业务层完全不用改动。
2. 方便单元测试,隔离外部依赖
做单元测试时,你可以快速写一个PriceTrackerDataSource的模拟实现(Mock),不用真的连接WebSocket。比如测试业务逻辑时,让模拟类返回固定的数据流,就能直接验证逻辑是否正确,不用依赖真实的网络环境,测试效率大幅提升。
3. 隐藏实现细节,降低协作成本
抽象类只对外暴露必要的接口(比如getActiveSymbols()),调用方根本不用关心内部是用WebSocket、本地缓存还是其他方式实现的。团队协作时,负责业务逻辑的同学不用啃底层连接的复杂代码,只需要知道接口的输入输出就行,认知负担大大降低。
4. 扩展性拉满,轻松切换或新增实现
如果后续要支持不同场景的数据源——比如测试环境用本地模拟数据,生产环境用WebSocket,只需要新增一个MockPriceTrackerDataSource实现类,然后通过依赖注入切换即可,完全不用改动现有业务代码。
举个直观对比:
如果直接用实现类,业务层代码会是这样:
class PriceTrackerBloc { final PriceTrackerDataSourceImpl _dataSource; PriceTrackerBloc(this._dataSource); // ...业务逻辑代码 }
要换实现的话,必须修改Bloc的构造参数类型,牵一发而动全身。
而用抽象类的话:
class PriceTrackerBloc { final PriceTrackerDataSource _dataSource; PriceTrackerBloc(this._dataSource); // ...业务逻辑代码 }
不管传的是PriceTrackerDataSourceImpl还是MockPriceTrackerDataSource,Bloc的代码完全不用改,灵活度直接拉满。
内容的提问来源于stack exchange,提问作者Ardeshir ojan

