You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 16:40:33