很多项目中都有消息分发或者事件通知机制,尤其是模块化程度高的项目。例如在办公自动化系统中,有些子系统对于新建用户这一事件很感兴趣,权限模块希望为这个新用户设置默认的权限,报表模块希望重新生成当月的报表,诸如此类的代码都写到新建用户的业务逻辑后面,会加大耦合度,可维护性降低,并且对于每个模块都是一个独立工程的情况,这种方式更是不可取。对于简单的情形,观察者模式就适用了,如果系统中有很多地方都需要收发消息,那么它就不适用了,否则会造成类数量的膨胀,增加类的复杂性,这时候就需要一种更集中的机制,Publish-Subscribe机制是个不错的选择,它的耦合性低,各个参与者之间毫无关联。每
一个消息都有一个唯一标识,一般都用字符串来描述,比如用户管理模块中新添加了一个用户,于是它发送了一个消息:/UserManagment/User /Add,消息的其他信息可以放置到一个Map中。下面是一个最简单的消息订阅接口:
public interface MessageSubscriber {
public void onRecived(String message,Map params);
}
当订阅的消息发出后,MessageSubscriber的onRecived方法就会被调用,消息相关的特定信息存储在参数params中。 一个消息可以被多个对象订阅,一个对象可以订阅多个消息,所以onRecived的第一个参数是消息的名称,如果对象订阅了多个消息,可能需要根据消息类型来进行具体的操作。
下面消息发送的实现类:
public class MessagePublisher {
private static MessagePublisher singleton;
private static Map<String,ArrayList<MessageSubscriber>> subscribers;
private MessagePublisher(){}
public static MessagePublisher instance(){
if(singleton == null)
singleton = new MessagePublisher();
return singleton;
}
public void register(String message,MessageSubscriber subscriber){
if(subscriber == null)
return;
if(subscribers == null)
subscribers = new LinkedHashMap<String, ArrayList<MessageSubscriber>>();
ArrayList<MessageSubscriber> subscriberList = subscribers.get(message);
if(subscriberList == null){
subscriberList = new ArrayList<MessageSubscriber>();
subscribers.put(message, subscriberList);
}
subscriberList.add(subscriber);
}
public void publish(String message, Map params){
if(subscribers == null)
return;
ArrayList<MessageSubscriber> subscriberList = subscribers.get(message);
if(subscriberList == null || subscriberList.isEmpty())
return;
for (MessageSubscriber topicSubscriber : subscriberList)
topicSubscriber.onRecived(message,params);
}
}
该类中主要包含两个方法:register用来注册消息订阅者,publish用来发送消息。这样,对某个事件感兴趣的模块就可以通过MessagePublisher来订阅这个相关的消息,而产生事件的模块就可以通过MessagePublisher将其发布出去,例如在新建用户逻辑的后面就可以加上以下代码片段
Map params = new LinkedHashMap();
params.put("id",newUserId);
params.put("name",newUserName);
MessagePublisher.instance().publish("/UserManagment/User/Add",params);
本文中的实例的唯一过滤依据就是消息的名称,在实际的项目中,过滤的方式可能更复杂,订阅者会提供其他过滤条件,只有这些条件被满足时,消息才会被发送给订阅者。另外,当消息发送出去后,订阅对象的onRecived方法会依次被调用,所以,订阅对象不应该在该方法中执行耗时操作,最好另外启动一个新线程来处理消息,不然会阻塞其他订阅对象收到该消息。
消息订阅机制的优点是大大降低了模块间的耦合度,相关操作都集中在MessagePublisher中;另外一个优点就是可扩展性强,随着系统越来越复杂,可以考虑把消息订阅和分发机制单独作为一个模块来实现,增加新特性以满足需求。消息订阅机制的缺点是发送者不能获知订阅者的执行情况。
分享到:
相关推荐
设计模式精解-GoF-23种设计模式解析--附C++源代码,帮助理解!
GoF的经典著作设计模式(Design Pattern)
自己去实现GoF的23中模式时候的知其然不知其所以然,并且有一天在自己设计的系统种由于设计的原因让自己苦不堪言,突然悟到了设计模 第 2 页 共 105 页 k_eckel 设计模式精解-GoF 23 种设计模式解析附 C++实现源码 ...
而思想则是指导行为的一切,理解和掌握了设计模式,并不是说记住了23种(或更多)设计场景和解决策略(实际上这也是很重要的一笔财富),实际接受的是一种思想的熏陶和洗礼,等这种思想融入到了你的思想中后,...
设计模式精解-GoF-23种设计模式解析,C++源码精解,创建型模式5种,结构性模式7种,行为模式11种。面向对象系统的分析和设计实际上追求的就是两点,一是高内聚(Cohesion),而是低耦合(Coupling)
设计模式精解- GoF 23种设计模式解析附C++实现源码 懂了设计模式,你就懂了面向对象分析和设计(OOA/D)的精要。反之好像也可能成立。道可道,非常道。道不远人,设计模式亦然如此。 一直想把自己的学习经验以及在...
本书设计实例从面向对象的设计中精选出23个设计模式,总结了面向对象设计中最有价值的经验,并且用简洁可复用的形式表达出来。本书分类描述了一组设计良好,表达清楚的软件设计模式,这些模式在实用环境下有特别有用...
设计模式精解-GoF23种设计模式解析(附C++实现源码)
GOF 设计模式 中文 高清 经典书籍 值得拥有 带目录 适合进阶
著名的EJB领域顶尖的专家Richard Monson-Haefel在其个人网站:www.EJBNow.com中极力推荐的GoF的《设计模式》,原文如下: Design Patterns Most developers claim to experience an epiphany reading this book....
GOF-设计模式-Design Patterns-英文原版-高清-有目录-有页码
学习设计模式好的资料学习设计模式好的资料学习设计模式好的资料学习设计模式好的资料学习设计模式好的资料学习设计模式好的资料学习设计模式好的资料学习设计模式好的资料学习设计模式好的资料
设计模式精解-GoF23种设计模式解析附C++实现源码,是系统学习设计模式,深入理解每种模式的原型,优缺点,适用的场景,达到灵活运用目的的最好参考书
GOF-TYPESCRIPT:GOF-设计图案-带类型脚本
GOF设计模式中英文+设计模式精解中英文,一共四个文档,高清版
设计模式精解-GoF 23种设计模式解析.pdf
设计模式精解-GoF 23种设计模式解析附C++实现源码
以文本和思维导图的方式简明扼要的介绍了GoF的23个经典设计模式,可当成学习设计模式的一个小手册,偶尔看一下,说不定会对大师的思想精髓有新的领悟。