MVP架构的Presenter层是否需要通过protocol实现代码松耦合?
关于MVP中Presenter层加Protocol的问题解答
1. 原有写法确实存在强耦合问题
你最初的ViewController直接声明presenter为WorkoutPresenter具体类的写法,确实会造成强耦合:
- ViewController直接依赖具体的Presenter实现,后续如果需要替换Presenter的业务逻辑、或者做单元测试替换为Mock实现,必须修改ViewController的代码
- 不符合依赖倒置原则,高层模块(视图层)直接依赖低层模块的具体实现,扩展成本高
2. 给Presenter加Protocol是标准的解耦方案,但是你的调整代码存在错误
你的加Protocol的思路是对的,但是示例代码里存在编译错误:你原来的WorkoutPresenter的初始化方法要求传入delegate参数,但是你调整后的ViewController里直接调用了无参数的WorkoutPresenter()初始化,会导致编译失败。
修正后的正确写法如下:
// 协议命名建议更清晰,比如用 WorkoutPresenterInterface 更直观 protocol WorkoutPresenterInterface { func startWorkout() func endWorkout() } // Presenter遵循协议 class WorkoutPresenter: WorkoutPresenterInterface { weak var delegate: WorkoutPresenterDelegate? init(delegate: WorkoutPresenterDelegate) { self.delegate = delegate } func startWorkout() { // 业务逻辑 } func endWorkout() { // 业务逻辑 } } // ViewController依赖协议而非具体类 class WorkoutViewController: UIViewController, WorkoutPresenterDelegate { // 声明为协议类型,初始化时传入delegate lazy var presenter: WorkoutPresenterInterface = WorkoutPresenter(delegate: self) }
3. 修正后的写法可以实现松耦合,核心收益如下
- 方便单元测试:你可以编写
MockWorkoutPresenter遵循WorkoutPresenterInterface协议,在测试ViewController时注入Mock实例,无需依赖真实的业务逻辑,快速验证视图交互逻辑 - 降低扩展成本:如果后续需要做不同版本的业务逻辑(比如免费版/付费版的训练流程不同),只需要新增对应遵循协议的Presenter实现,ViewController代码无需任何修改
- 接口隔离:协议只暴露ViewController需要调用的方法,Presenter内部的其他逻辑不会对外暴露,保证接口最小化
4. 关于网上不同方案的说明
部分小项目会省略Presenter层的Protocol,本质是牺牲可测试性和扩展性来减少样板代码、提升开发效率。如果你的项目是需要长期维护、需要写单元测试的中大型项目,建议加上Protocol;如果是一次性的小demo,也可以根据实际情况选择省略。
内容的提问来源于stack exchange,提问作者TeddyKen
相关产品推荐
相关产品推荐

