Unity通用MVP架构实现求助:组件关联逻辑与命名空间问题
Unity MVP 通用实现方案与问题修复
核心问题分析
你的当前实现存在两个关键问题:
- 耦合过重:View直接实例化Presenter,同时Model直接依赖具体Presenter类,违反了MVP的依赖倒置原则,导致组件难以独立测试和扩展
- 命名空间冗余:类名和命名空间同名(比如
Presenter命名空间下的Presenter类),导致必须用全限定名调用
问题修复步骤
1. 解决命名空间冗余问题
直接调整命名空间和类名的对应关系,避免同名冲突:
- 把命名空间改为
YourProject.MVP(或更贴合项目的名称),类名保持Presenter、Model、View - 或者保持命名空间,但类名改为
BasePresenter、BaseModel、BaseView,后续自定义类继承这些基类
调整后的命名空间示例:
namespace YourProject.MVP { public interface IPresenter { /* ... */ } public class Presenter : IPresenter { /* ... */ } }
导入命名空间后,就可以直接使用Presenter而不是Presenter.Presenter。
2. 重构组件关联逻辑,引入初始化器
创建专门的初始化逻辑,让View不再直接依赖具体Presenter,而是由统一的初始化类完成组件关联:
调整后的接口定义
// IView.cs public interface IView { IPresenter Presenter { get; set; } void OnInit(); } // IPresenter.cs public interface IPresenter { IView View { get; set; } IModel Model { get; set; } } // IModel.cs public interface IModel { IPresenter Presenter { get; set; } }
基类实现
// BaseView.cs(所有View的基类,继承MonoBehaviour) public class BaseView : MonoBehaviour, IView { [SerializeField] private bool autoInitialize = true; public IPresenter Presenter { get; set; } public virtual void OnInit() { } private void Awake() { if (autoInitialize) { MVPInitializer.Initialize(this); } } } // BasePresenter.cs public class BasePresenter : IPresenter { public IView View { get; set; } public IModel Model { get; set; } public virtual void Initialize(IView view, IModel model) { View = view; Model = model; Model.Presenter = this; View.OnInit(); } } // BaseModel.cs public class BaseModel : IModel { public IPresenter Presenter { get; set; } }
初始化器实现
// MVPInitializer.cs public static class MVPInitializer { // 泛型方法,支持自定义View、Presenter、Model public static void Initialize<TView, TPresenter, TModel>(TView view) where TView : BaseView, IView where TPresenter : BasePresenter, new() where TModel : BaseModel, new() { var presenter = new TPresenter(); var model = new TModel(); presenter.Initialize(view, model); view.Presenter = presenter; } // 默认基类简化调用 public static void Initialize(BaseView view) { Initialize<BaseView, BasePresenter, BaseModel>(view); } }
通用可扩展的MVP使用方式
自定义业务模块时,只需继承基类扩展即可:
// 自定义登录View public class LoginView : BaseView { public Button loginButton; public InputField usernameInput; public override void OnInit() { loginButton.onClick.AddListener(() => ((LoginPresenter)Presenter).OnLoginClicked(usernameInput.text)); } public void ShowLoginSuccess() { // 登录成功后的UI更新逻辑 } } // 自定义登录Presenter public class LoginPresenter : BasePresenter { public void OnLoginClicked(string username) { ((LoginModel)Model).SaveUsername(username); ((LoginView)View).ShowLoginSuccess(); } } // 自定义登录Model public class LoginModel : BaseModel { public string Username { get; private set; } public void SaveUsername(string username) { Username = username; } }
给场景UI对象添加LoginView组件后,初始化器会自动创建对应的LoginPresenter和LoginModel并完成关联。
内容的提问来源于stack exchange,提问作者Kuzmych Maksym
相关产品推荐
相关产品推荐

