移动项目开发笔记(.Net下的观察者(Observer)模式)
一、发布订阅模型(pub-sub)
二、动机(Motivation)
在软件构建过程中,我们需要为某些对象建立一种 "通知依赖关系" ——一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得
到通知。如果这样的依赖关系过于紧密,将使软件不能很好地抵御变化。
使用面向对象技术,可以将这种依赖关系弱化,并形成一种稳定的依赖关系。从而实现软件体系结构的松耦合。
三、意图(Intent)
定义对象间的一种一对多的依赖关系,以便当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动更新
——《设计模式》GoF
四、结构
五、Observer模式的几个要点
使用面向对象的抽象,Observer模式使得我们可以独立地改变目标与观察者,从而使二者之间的依赖关系达致松耦合。
目标发送通知时,无需指定观察者,通知(可以携带通知信息作为参数)会自动传播。观察者自己决定是否需要订阅通知,目标对象对此一无所
知。
在C#的event中,委托充当了抽象的Observer接口,而提供事件的对象充当了目标对象。委托是比抽象Observer接口更为松耦合的设计。
六、项目中运用的发布订阅模式的实际例子:(这里实际上运用了observer模式的扩展)需求是:当一个对象的状态发生了变化(这里是传入一个消息给一个对象),那么所有监听这个对象的其他对象会根据指定的接收对象的类型调用指定对象的方法:我们都很清楚的了解到observer模式主要是用于当一个对象的状态发生变化的时候,会自动的通知订阅的其他对象,也就是说会把当前的消息传递给其他对象进行处理。但是有一个问题是,如果其他对象接收到的消息是由限制的,像某个对象只能接收指定类型的消息等,这样的话就需要在以前的observer模式上进行补充:
下面是项目中关于这个模式的的结构如图:
首先来看看Listener文件夹下的一个文件(其他几个文件类似)
[KnowType(typeof(float))]
publicclassDesignApprovalListener:IActionListener
{
publicboolRun(objectvalue)
{
returntrue;
}
}
其中KnowType是一个自定义的属性,代码如下:
[AttributeUsage(AttributeTargets.Class,AllowMultiple=true)]
publicclassKnowTypeAttribute:Attribute
{
privatestringm_typeName;
publicstringTypeName
{
get{returnm_typeName;}
}
publicKnowTypeAttribute(TypemodelType)
{
this.m_typeName=modelType.FullName;
}
}
IActionListener是一个接口:
publicinterfaceIActionListener
{
///summary
///订阅接受方法
summary
///paramname="value"DomainModelorDataEntity/param
///returns执行成功返回True,否则为false/returns
boolRun(objectvalue);
}
其中的核心方法是通过反射得到所有监听的对象所需要接受对象的类型,这样就可以调用指定对象的方法,而不是调用所有监听者的方法:下面是这个方法的核心:
Core文件夹下的MonitorFactory.cs文件就是完成这一个功能,代码如下:
Code
publicstaticboolPublisher(objectarg)
{
boolresult=false;
if(configuration!=nullconfiguration.Listeners!=nullconfiguration.Listeners.Count0)
{
RegisteredListenerlistener=null;
foreach(ListenerItemiteminconfiguration.Listeners)
{
if(item.Valid)
{
listener=ActivatorListener(item.ClassName);
if(listener!=null)
{
if(listener.RegisteredTypes==null||listener.RegisteredTypes.Length==0)
{
result=listener.CurrentListener.Run(arg);
}
else
{
foreach(KnowTypeAttributeattributeIteminlistener.RegisteredTypes)
{
if(arg.GetType().FullName==attributeItem.TypeName)
{
result=listener.CurrentListener.Run(arg);//这里是调用指定对象的方法
}
}
}
}
}
}
}
returnresult;
}
Code
///summary
///创建Listener实例并获取Attribute
summary
///paramname="className"/param
///returns/returns
privatestaticRegisteredListenerActivatorListener(stringclassName)
{
RegisteredListenerresult=null;
if(registeredContainer.ContainsKey(className))
{
result=registeredContainer[className];
}
else
{
Typetype=Type.GetType(className);
if(type!=null)
{
KnowTypeAttribute[]registerType=type.GetCustomAttributes(typeof(KnowTypeAttribute),false)asKnowTypeAttribute[];
IActionListenerlistenerInstance=Activator.CreateInstance(type)asIActionListener;
result=newRegisteredListener(listenerInstance,registerType);
registeredContainer.Add(className,result);
}
}
returnresult;
}
注册监听对象对象是通过代码指定的,当然可以通过一个xml文件来配置节点来实现,那样会更加灵活
Code
privatestaticDictionarystring,RegisteredListenerregisteredContainer;
privatestaticMonitorConfigurationconfiguration;
staticMonitorFactory()
{
configuration=newMonitorConfiguration();
configuration.Listeners=newListListenerItem();
ListenerItemitem=newListenerItem();
item.ClassName="ProjectEstablishRequestListener";
configuration.Listeners.Add(item);
item=newListenerItem();
item.ClassName="ProjectApprovalListener";
configuration.Listeners.Add(item);
item=newListenerItem();
item.ClassName="DesignApprovalListener";
configuration.Listeners.Add(item);
registeredContainer=newDictionarystring,RegisteredListener();
foreach(ListenerItemlistenerinconfiguration.Listeners)
{
if(listener.Valid)
{
ActivatorListener(listener.ClassName);
}
}
}
这里就不展示其他代码了,总之思想就是这样,通过在Listener的类文件中通过属性来制定这个对象接受的消息类型,最后遍历所有的监听者对象看是否满足指定的消息类型,最后调用指定的对象的方法。这样就达到了项目中的需求。
推荐资源
*《设计模式:可复用面向对象软件的基础》GoF
*《面向对象分析与设计》Grady Booch
*《敏捷软件开发:原则、模式与实践》Robert C. Martin
*《重构:改善既有代码的设计》Martin Fowler
*《Refactoring to Patterns》Joshua Kerievsky
更多MSDN资源
*MSDN中文网站
http://www.microsoft.com/china/msdn
*MSDN中文网络广播
http://www.msdnwebcast.com.cn/
*MSDN Flash
http://www.microsoft.com/china/newsletter/case/msdn.aspx
*MSDN开发中心
http://www.microsoft.com/china/msdn/DeveloperCenter/default.mspx
转载于:https://www.cnblogs.com/gnhao/archive/2013/01/08/2850611.html
移动项目开发笔记(.Net下的观察者(Observer)模式)相关推荐
- [Openwrt 项目开发笔记]:Samba服务vsFTP服务(四)
[Openwrt项目开发笔记]系列文章传送门:http://www.cnblogs.com/double-win/p/3888399.html 正文: 在上一节中,我们讲述了如何在路由器上挂载U盘,以 ...
- 京东投票项目开发笔记
京东投票项目开发笔记 打开项目 $yarn install / $ npm install: 跑环境(把项目依赖的插件进行安装) $node admin.js: 启服务(把自己的计算机作为服务器,创建 ...
- 京东抽奖项目开发笔记
京东抽奖项目开发笔记 前言: 这是一个独立项目,这个项目会由我们四个人来一起完成,所以首先就要分工合作,我是写前端的,所以我会先把基本的页面写出来 1.注册页 这是注册页的代码 <!DOCTYP ...
- 尚硅谷前端项目开发笔记
尚硅谷前端项目开发笔记 B站视频直达,这个项目亮点在于所有 API 请求都并非在组件内编写,而是在组件内使用this.$store.dispatch() 派发任务,再由 Vuex(actions.mu ...
- [Openwrt 项目开发笔记]:Openwrt平台搭建(一)
[Openwrt项目开发笔记]系列文章传送门:http://www.cnblogs.com/double-win/p/3888399.html 正文: 最近开始着手进行Openwrt平台的物联网网关设 ...
- 天天生鲜项目开发笔记
天天生鲜项目开发笔记 说在前面的话 大学四年,忙忙碌碌,什么都学了,又好像什么都没学,总之要毕业了,毕设题目是"生鲜配送系统",B站上找到了一个天天生鲜的项目开发教程,之后文章记录 ...
- Vue PC商城项目开发笔记与问题汇总
Vue PC商城项目开发笔记与问题汇总 负责PC端商城项目,这也是人生第一个真正的项目.刚做了一天,就遇到不少问题,在这里列出自己的问题与解决办法,与大家交流,提升自己,希望以后不会掉进同一个坑里. ...
- ZYNQ LINUX开发笔记——windows下用xilinx SDK编译zynq linux app小程序
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 ZYNQ LINUX开发笔记--windows下用xilinx SDK编译zynq linux app小程序 前言 操作方法 总结 前 ...
- 设计模式学习笔记——观察者(Observer)模式
设计模式学习笔记--观察者(Observer)模式 @(设计模式)[设计模式, 观察者模式, Observer] 设计模式学习笔记观察者Observer模式 基本介绍 观察者案例 类图 实现代码 Ob ...
最新文章
- python读出文件中的内容_Python读取文本内容
- sqlplus登录Oracle时ORA-01017: invalid username/password; logon denied的错误
- python自然语言处理库_Python自然语言处理工具库(含中文处理)
- 第十章 深入理解Session与Cookie
- quartz定时任务中常用的cron表达式
- 动手刷LeetCode-转换罗马字符
- MATLAB 中gcf、gca 以及gco 的区别
- 计算机一级最强大脑,计算机入侵人类 《最强大脑》选手完败?
- 计算机计算涨跌的公式,计算股票涨跌的神器—四段五点模型计算器
- iOS平台游戏安全之IPA破解原理及防御
- Hyperf基础使用
- 为SEO而生的Rabbit V1.0 WordPress主题下载
- marquee标签_html滚动文字
- 使用MFC画线(初学)
- Keil uVision5 创建工程(STM32F051C8T6)
- 1990-2021年全国各省外商直接投资水平
- Execution repackage of goal org.springframework.boot:spring-boot-maven-plugin:2.4.0:repackage failed
- php for循环逗号,关于php:从foreach循环中删除最后一个逗号
- thymeleaf里面遇到的关于th:field的坑
- 二进制格式mysql安装