The Observer Design Pattern

观察者模式

Like the use of interfaces, the Observer design pattern can be used to decouple components and enable extensibility without modification (observing the Open Closed Principle). It also contributes to achieving separation of concerns.
Consider, for example, an object that handles user login. There might be several outcomes from a user's attempt to login: successful login; failed login due to an incorrect password; failed login due to an incorrect username and password; system error due to failure to connect to the database that holds login information.

与接口的用法一样,观察者设计模式能被用于解耦组件和增加可扩展性(遵守开闭原则)。它也有助于完成关注点分离。

举个例子,一个处理用户登录的对象。对于一个用户登录可能有多个输出:成功登录,由于密码错误登录失败;由于用户名和密码错误登录失败;系统错误由于连接数据库失败。

Let's imagine that we have a login implementation working in production, but that further requirements mean that the application should e-mail an administrator in the event of a given number of system errors; and should maintain a list of incorrectly entered passwords, along with the correct passwords for the users concerned, to contribute to developing information to help users avoid common errors. We would also like to know the peak periods for user login activity (as opposed to general activity on the web site).

让我们想想在产品中有一个实现登录的流程,但是将来的需求意味着这个应用可以在给定数量的系统错误的时候发email给管理员;应该维护一个不正确输入的密码的列表,与用户正确的密码关联,致力于开发信息帮助用户避免密码普通错误。我们也喜欢了解高峰时期用户登录的活动(想对于在网站上的一般活动)。

All this functionality could be added to the object that implements login. We should have unit tests that would verify that this hasn't broken the existing functionality, but this is approach doesn't offer good separation of concerns (why should the object handling login need to know or obtain the administrator's e-mail address, or know how to send an e-mail?). As more features (or aspects) are added, the implementation of the login workflow itself – the core responsibility of this component – will be obscured under the volume of code to handle them.

所有的这些功能应该被增加到实现登录的对象上。我们应该有单元测试验证这些没有破坏存在的功能,但是这只是一个途径,它没有提供好的关注点的分离(为什么对象处理登录需要知道或获取管理员的email地址,或者知道如何去发送email?)随着更多的特性被增加,登录工作流的实现--核心的职责的组件-将被遮掩在代码具体细节上。

We can address this problem more elegantly using the Observer design pattern. Observers (or listeners) can be notified of application events. The application must provide (or use a framework that provides) an event publisher. Listeners can register to be notified of events: all workflow code must do is publish events that might be of interest. Event publication is similar to generating log messages, in that it doesn't affect the working of application code. In the above example, events would include:

我们能处理这个问题更优美的用观察者模式。观察者模式(或者监听者)能被应用程序的事件通知。应用程序必须提供(或者用框架提供)事件的发布者。监听者能注册到事件的通知:所有的工作流代码必须做的是发布可能是感兴趣的事件。事件发布者与产生日志信息的事件相似,所以他不影响应用代码的流程。在上面的例子中,事件必须包含:

  • Attempted login, containing username and password

  • 尝试登陆,包含用户名和密码

  • System error, including the offending exception

  • 系统错误,包含错误异常

  • Login result (success or failure and reason)

  • 登陆结果(成功或者失败和原因)

Events normally include timestamps.

事件应该包含时间戳。

Now we could achieve clean separation of concerns by using distinct listeners to e-mail the administrator on system errors; react to a failed login (added it to a list); and gather performance information about login activity.

现在我们能完成关注点的清晰分离,利用有区别的监听器去email管理员当系统错误的时候;对一个失败的登陆做出反应;收集关于登陆活动的性能信息。

The Observer design pattern is used in the core Java libraries: for example, JavaBeans can publish property change events. In our own applications, we will use the Observer pattern at a higher level. Events of interest are likely to relate to application-level operations, not low-level operations such as setting a bean property.

观察者设计模式被用于在java的核心包中:举个例子,javabean能发行属性改变的事件。在我们自己的应用中,我们将用观察者模式在一个更高的层次。感兴趣的事件更可能关联应用级别的操作,不是底级别的操作如设置bean属性。

Consider also the need to gather performance information about a web application. We could build sophisticated performance monitoring into the code of the web application framework (for example, any controller servlets), but this would require modification to those classes if we required different performance statistics in future. It's better to publish events such as "request received" and "request fulfilled" (the latter including success or failure status) and leave the implementation of performance monitoring up to listeners that are solely concerned with it. This is an example of how the Observer design pattern can be used to achieve good separation of concerns. This amounts to Aspect-Oriented Programming, which we discuss briefly under Using Reflection later.

考虑需要收集web应用的性能信息。我们能构建复杂的性能监控web框架的代码(举个例子,任何servlets控制),但是这需要对类修改如果我们要求不同的性能数据在将来。倒不如去发布事件例如“请求接收”和“请求满足”(后者包含成功或失败的状态),留下监控性能的实现到监听器中,这个监听器仅仅考虑他。这是观察者模式如何被用于完成好的关注点的分离。大量的面向切面编程,将被简短的讨论在用了反射以后。

Don't go overboard with the Observer design pattern: it's only necessary when there's a real likelihood that loosely coupled listeners will need to know about a workflow. If we use the Observer design pattern everywhere our business logic will disappear under a morass of event publication code and performance will be significantly reduced. Only important workflows (such as the login process of our example) should generate events.

不要滥用观察者模式:它仅仅是必要的当这里有一个真的可能,松耦合监听器需要知道工作流程。如果我们再我们业务逻辑的任何地方用观察者模式将

消失在一大堆事件发布代码上和严重的性能降低。仅仅对重要的工作流应该产生事件(例如登陆的例子)。

A warning when using the Observer design pattern: it's vital that listeners return quickly. Rogue listeners can lock an application. Although it is possible for the event publishing system to invoke observers in a different thread, this is wasteful for the majority of listeners that will return quickly. It's a better choice in most situations for the onus to be on listeners to return quickly or spin off long-running tasks into separate threads. Listeners should also avoid synchronization on shared application objects, as this may lead to blocking. Listeners must be threadsafe.

用观察者模式的一个警告:监听器返回快速是很重要的。糟糕的监听器可以锁住一个应用,即使它是可能的为事件发布系统去调用观察者在一个不用的线程中,这是浪费的对于一个主监听器快速的返回。更好的方法是,在大部分的情形下职责监听器应该返回快速的,或者剥离长时间运行的任务到分离的线程。

监听器应该避免一步调用在分享的应用对象中,因为这个可能导致阻塞。监听器必须是线程安全的。

The Observer design pattern is less useful in a clustered deployment than in deployment on a single server, as it only allows us to publish events on a single server. For example, it would be unsafe to use the Observer pattern to update a data cache; as such an update would apply only to a single server. However, the Observer pattern can still be very useful in a cluster. For example, the applications discussed above would all be valid in a clustered environment. JMS can be used for cluster-wide event publication, at the price of greater API complexity and a much greater performance overhead.

观察者设计模式在一个集群的部署中是无用的,比起单个的应用来说,因为它仅仅允许我们发布事件在单个服务器上。举个例子,它将是不安全的用观察者模式更新数据缓存;例如一个更新将仅仅对一个单个的服务有用。然而,观察者模式任然有用在分布式系统中。举个例子,上面讨论的应用在一个集群的环境中是有效的。jms能被用于广泛的集群事件发布,在复杂api的花费和一个巨大的性能开销。

In my experience, the Observer design pattern is more useful in the web tier than in the EJB tier. For example, it's impossible to create threads in the EJB tier (again, JMS is the alternative).

根据我的经验,观察者模式更多的用于web层比起ejb层。举个例子,在ejb层创建一个线程是不可能的(再次,jms是可选的)。

In Chapter 11 we look at how to implement the Observer design pattern in an application framework. The application framework infrastructure used in the sample application provides an event publication mechanism, allowing approaches such as those described here to be implemented without the need for an application to implement any "plumbing".

在11章我们着眼于如何实现观察者模式在应用框架中。这个应用框架基础设施用于简单的应用提供事件发布机制,允许处理例如这些在这儿被描述的去实现

不需要一个应用去实现任何管道。

转载于:https://www.cnblogs.com/sqtds/archive/2012/11/25/2788269.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值