MVFM框架----模块间最大化解耦之广播监听模式
来源:互联网 发布:windows shell 编辑:程序博客网 时间:2024/05/29 10:30
虽说大部分的逻辑交互可以通过数据绑定和命令绑定实现,但依然有些需求需要在逻辑模块中涉及到UI.比如说--提示。
有些逻辑处理结果需要展示给用户看,展示的方式很多样。如,界面弹框,提示等等。由于展示都是临时性的,通过绑定展示的话并不是好的选择,那怎么办呢?我选择用广播监听的方式。
大概原理是:逻辑处理完成后,广播一个特定的信号出去,信号中附加参数,接收到的模块自己选择处理方式。
看下面的代码:
public delegate void Handler(object sender, CommonEventArgs e); public static class EventDispatcher { #region Private private static Dictionary<string, Dictionary<string, Handler>> TypeHandlers = new Dictionary<string, Dictionary<string, Handler>>(); #endregion #region FireEvent Function public static void FireEvent(object Sender, string KeyType, string Key, CommonEventArgs e) { if (!TypeHandlers.ContainsKey(KeyType)) return; Dictionary<string, Handler> Handlers = TypeHandlers[KeyType]; if (Handlers != null && Handlers.ContainsKey(Key)) { Handlers[Key](Sender, e); } } public static void FireEvent(object sender, string key, CommonEventArgs e) { FireEvent(sender, BaseEventKeys.DefaultKeyType, key, e); } public static void FireEvent(string key, CommonEventArgs e) { FireEvent(null, BaseEventKeys.DefaultKeyType, key, e); } #endregion #region Register Function public static void RegisterHandler(string KeyType, string Key, Handler Func) { if (string.IsNullOrEmpty(Key) || Func==null) { throw new Exception("Invalid Key or Function"); } Dictionary<string, Handler> Handers = GetKeyTypeList(KeyType); if (Handers.ContainsKey(Key)) { Handers[Key] += Func; } else { Handers.Add(Key, Func); } } public static void RegisterHandler(string key, Handler func) { RegisterHandler(BaseEventKeys.DefaultKeyType, key, func); } #endregion #region UnRegister Function public static void UnRegisterHandler(string key) { UnRegisterHandler(BaseEventKeys.DefaultKeyType,key,null); } public static void UnRegisterHandler(string KeyType, string Key, Handler Func) { Dictionary<string, Handler> Handlers = GetKeyTypeList(KeyType); if (Handlers == null || !Handlers.ContainsKey(Key)) return; if (Func == null) Handlers.Remove(Key); else { Handlers[Key] -= Func; if (Handlers[Key]==null) Handlers.Remove(Key); } } #endregion #region Private Function private static Dictionary<string, Handler> GetKeyTypeList(string KeyType) { if (string.IsNullOrEmpty(KeyType)) { throw new Exception("Invalid KeyType"); } if (!TypeHandlers.ContainsKey(KeyType)) { Dictionary<string, Handler> EventHandlers = new Dictionary<string, Handler>(); TypeHandlers.Add(KeyType, EventHandlers); return EventHandlers; } return TypeHandlers[KeyType]; } #endregion }EventDispatcher 的主要作用是处理信号注册和信号广播,这是一个静态类,不需要实例化既可以直接使用,可用于任何模块之间的交互。
RegisterHandler用于监听信号,KeyType是信号域,Key是信号域下的子信号,Func是处理此信号的函数。由于信号可能很多,而且有些信号是同一种类别,所以我加上了信号域的概念。注册的时候不填写信号域就会使用默认的信号域。
所有的信号都存储在TypeHandlers中,这是个哈希表,所以不用担心信号过多时会出现性能问题。
FireEvent用于广播信号,Sender为发送者,KeyType为信号域,Key是信号e则是信号所附带的参数。
e的类型为CommonEventArgs,以下为它的代码:
public class CommonEventArgs : EventArgs { private Dictionary<string, object> args = new Dictionary<string, object>(); public Handler Handler; public CommonEventArgs() { } public CommonEventArgs(string argName, object argValue) { args.Add(argName, argValue); } public void Add(string argName, object argValue) { args.Add(argName, argValue); } public T Get<T>(string argName) { return args.ContainsKey(argName) ? (T)args[argName] : default(T); } public object Get(string argName) { return args.ContainsKey(argName) ? args[argName] : default(object); } public T Get<T>(string argName,T defaultValue) { return args.ContainsKey(argName) ? (T)args[argName] : defaultValue; } }这个类中将附带信号处理所需的所有数据,数据存储在args中,这依然是个哈希表。通过事先约定好的键值进行存储。另外还有个Handler参数,这个参数可以用于回掉。当摸个信号接收到并处理完成后,可以用Handler参数反馈给发送着。
下面看一下简单的使用方法,首先定义信号域和子信号:
public class BaseEventKeys{ /// <summary> /// 数据模板 /// </summary> public static string Protocol = "Protocol"; /// <summary> /// 默认类型 /// </summary> public static string DefaultKeyType = "Default"; }信号域和子信号都是string类型,DefaultKeyType为默认信号域,Protocol则为默认的子信号。
假定有以下逻辑需要实现:某个数据列表需要从服务器获取数据源,当异步获取数据成功时,在当前界面想用户进行提示“获取数据成功!”。
首先在BaseEventKeys中添加信号GetDataSucced:
public static string GetDataSucced= "Succed";然后在当前页面注册此信号:
public sealed partial class GroupedItemsPage : MvfmText.Common.LayoutAwarePage { public GroupedItemsPage() { this.InitializeComponent(); } protected override void OnNavigatedTo(NavigationEventArgs e) { base.OnNavigatedTo(e); EventDispatcher.RegisterHandler(BaseEventKeys.GetDataSucced, GetDataSucced); } void GetDataSucced(object sender, CommonEventArgs e) { string msg = e.Get<string>(BaseEventKeys.Protocol); if (!string.IsNullOrEmpty(msg)) MessageBox.Show(msg); } }最后当需要提醒用户只需调用以下代码即可:
EventDispatcher.FireEvent(BaseEventKeys.GetDataSucced, new CommonEventArgs(BaseEventKeys.Protocol, "获取数据成功!"))是不是很简单!使用这种模式传递信息的好处在于模块之间最大化的解耦,同时又完成了模块之间的通信。这种通信方式符合设计模式四原则中的迪米特法则。
- MVFM框架----模块间最大化解耦之广播监听模式
- MVFM框架----概述
- MVFM框架----示例
- 监听电池电量之粘性广播
- Android广播接收器监听多个广播及多个广播接收器监听同一个广播_广播之二
- Android-WiFi开发之 WiFi广播监听
- 广播监听
- 使用javascript模拟观察者模式和事件监听广播机制
- android 飞行模式 注册广播后 三种状态监听
- android 飞行模式 注册广播后 三种状态监听
- 动态注册广播,监听网络状态变化,判断网络模式
- 系统广播监听飞行模式和耳机状态
- 用代码和UML图化解设计模式之《策略模式》
- 用代码和UML图化解设计模式之《代理模式》
- 用代码和UML图化解设计模式之《工厂模式》
- 用代码和UML图化解设计模式之《抽象工厂模式》
- 用代码和UML图化解设计模式之《门面模式》
- 用代码和UML图化解设计模式之《适配器模式》
- POJ 2251 ——Dungeon Master
- SQLite 创建与打开
- Setting up Mercurial on Mac
- 指针自身的地址、指针保存的地址和指针保存地址处的内容,为什么使用指针
- 3.跟我一起学建站之hibernate Helloworld xml版
- MVFM框架----模块间最大化解耦之广播监听模式
- UIPageControl 分页控件-IOS开发
- 敏捷开发实践初体验
- Fragment 实例(1234)
- ExpandableListActivity学习笔记
- 你的网站适合用Drupal搭建吗
- POJ3258--River Hopscotch
- Android菜单详解(四)——使用上下文菜单ContextMenu
- 关于深搜。。