命令(命令模式)、事件(观察者模式)在MVC框架中的应用

0、写在前面的话

我创建的Unity、C#交流群,有兴趣可加入大家一起学习(人还很少,现在加入就是元老🙀,群里面聊天不限于技术话题):952914223

1、简介

在客户端开发(如 Unity 游戏、桌面程序等)中,MVC 架构是一种经典的分层模式,用于实现逻辑分离、解耦模块、提高可维护性。而在 MVC 的实际落地过程中,命令模式与事件(观察者)模式起到了核心作用。
本文将以实际项目中常见的 MVC 变体结构为例,讲解命令与事件在其中的作用、职责划分,并配以结构图和示例代码。

2、基础概念回顾

1. 命令模式(Command Pattern)

将请求封装为对象,从而使你可以将请求参数化、排队执行或撤销操作。

在 MVC 中用于封装业务逻辑,如购买物品、发起战斗等。

  1. 观察者模式(Observer Pattern)

对象之间形成一种一对多的依赖关系,当一个对象状态变化时,依赖它的对象会收到通知并自动更新。

在 MVC 中用于通知 View 层更新 UI,例如金币数变化时刷新显示。
二、命令与事件在 MVC 中的职责划分

我们采用一种精简的 MVC架构:

用户点击 → View → 发送命令 → Command → 更新 Model → 分发事件 → View UI刷新

图示结构:
±---------- + ±------------+ ±-----------+ ±---------+
| View | ----> | Command | -----> | Model | ----> | View |
|(用户操作)| |(业务逻辑) | |(数据变更)| |(刷新UI)|
±----------+ ±------------+ ±-----------+ ±---------+
#3、代码示例(Unity / C#)
以用户购买金币为例,制作简易MVC架构,项目结构:

/Scripts
├── Framework
│ ├── ICommand.cs(命令接口)
│ ├── CommandDispatcher.cs(命令分发)
│ ├── EventSystem.cs(事件系统)
├── Model
│ └── GoldModel.cs(金币model)
├── Command
│ └── BuyGoldCommand.cs(购买金币命令)
├── View
│ └── ShopView.cs(商店页面)
└── Main
└── AppStartup.cs(程序入口)

程序逻辑:

[User点击按钮]

[View] → 调用 dispatcher.Execute(“BuyGold”)

[BuyGoldCommand] → 修改 GoldModel(比如增加200金币)

[GoldModel] → Dispatch(“GoldChanged”, 新值)

[View] ← 监听事件 On(“GoldChanged”) 并更新 UI 显示

✅ 1. ICommand 接口

public interface ICommand
{
    void Execute(object data = null);
}

✅ 2. CommandDispatcher 命令调度器

using System.Collections.Generic;

public class CommandDispatcher
{
    private Dictionary<string, ICommand> _commandMap = new();

    public void Register(string key, ICommand command)
    {
        _commandMap[key] = command;
    }

    public void Execute(string key, object data = null)
    {
        if (_commandMap.TryGetValue(key, out var cmd))
        {
            cmd.Execute(data);
        }
        else
        {
            UnityEngine.Debug.LogWarning($"Command '{key}' not registered.");
        }
    }
}

✅ 3. EventSystem 简易事件系统

using System;
using System.Collections.Generic;

public static class EventSystem
{
    private static Dictionary<string, Action<object>> _events = new();

    public static void On(string key, Action<object> listener)
    {
        if (!_events.ContainsKey(key))
            _events[key] = _ => { };
        _events[key] += listener;
    }

    public static void Off(string key, Action<object> listener)
    {
        if (_events.ContainsKey(key))
            _events[key] -= listener;
    }

    public static void Dispatch(string key, object data = null)
    {
        if (_events.TryGetValue(key, out var callback))
        {
            callback?.Invoke(data);
        }
    }
}

✅ 4. GoldModel 单例模型

public class GoldModel
{
    public static GoldModel Instance { get; } = new();

    public int Gold { get; private set; } = 1000;

    public void AddGold(int amount)
    {
        Gold += amount;
        EventSystem.Dispatch("OnGoldChanged", Gold);
    }
}

✅ 5. BuyGoldCommand 命令类

public class BuyGoldCommand : ICommand
{
    public void Execute(object data = null)
    {
        int amount = data is int val ? val : 100;
        GoldModel.Instance.AddGold(amount);
    }
}

✅ 6. ShopView 示例 View

using UnityEngine;
using UnityEngine.UI;

public class ShopView : MonoBehaviour
{
    public Text goldText;
    public Button buyButton;

    private CommandDispatcher dispatcher;

    void Start()
    {
        dispatcher = new CommandDispatcher();
        dispatcher.Register("BuyGold", new BuyGoldCommand());

        buyButton.onClick.AddListener(() =>
        {
            dispatcher.Execute("BuyGold", 200);
        });

        EventSystem.On("OnGoldChanged", OnGoldChanged);
        goldText.text = "Gold: " + GoldModel.Instance.Gold;
    }

    void OnGoldChanged(object gold)
    {
        goldText.text = "Gold: " + gold;
    }

    void OnDestroy()
    {
        EventSystem.Off("OnGoldChanged", OnGoldChanged);
    }
}

✅ 7. AppStartup 启动注册(可选)
如果你要全局注册命令和模型,可以用一个入口类统一初始化:

public class AppStartup : MonoBehaviour
{
    public static CommandDispatcher Dispatcher { get; private set; }

    void Awake()
    {
        Dispatcher = new CommandDispatcher();
        Dispatcher.Register("BuyGold", new BuyGoldCommand());
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值