您的位置:首页 > 其它

观察者模式 - 行为模式

2015-07-18 13:08 302 查看
个人补充:


此模式可以用JKD自带的接口observer和类Observable来实现一个观察者模式。观察者实现observer类中的update方法,被观察者继承Observable类。

查看Observable类,可以看到addObserver、deleteObserver、notifyObservers等方法,而且都做了同步处理,有现成的,就拿过来直接用就行。

模式类型:

Observer 观察者模式 - 行为模式

意图:

Defines a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.

定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

概述:

简单来说,observer必须实现update方法,来接收suject状态变化时的通知及更新。suject维护一个observer列表,在状态变化时会逐个的调用observer的update方法来通知、更新observer,为此,suject须提供注册(添加observer到列表)、删除、通知更新三个方法。

观察者模式又分为两种模式:push和pull。push是指suject在状态变化时将所有的状态信息都发给observer,pull则是suject通知observer更新时,observer获取自己感兴趣的状态。

两种模式在实现上的区别:push模式下,observer的update方法接收的是状态信息,而pull模式下,update方法接收的是suject对象,这种情况下,suject须提供状态信息的get方法,让observer可以获取自己感兴趣的信息。

两种模式的优劣:push模式要求suject必须了解observer需要的状态,pull则是observer按需获取;push模式下observer的update方法的参数是具体的状态信息,发生变化时必须要重写update方法,pull模式则是将suject对象本身传给update,是最大的参数集合。

角色:

抽象主题角色:把所有对观察者对象的引用保存在一个集合中,每个抽象主题角色都可以有任意数量的观察者。抽象主题提供一个接口,可以增加和删除观察者角色。一般用一个抽象类和接口来实现。

抽象观察者角色:为所有具体的观察者定义一个接口,在得到主题的通知时更新自己。

具体主题角色:在具体主题内部状态改变时,给所有登记过的观察者发出通知。具体主题角色通常用一个子类实现。

具体观察者角色:该角色实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态相协调。通常用一个子类实现。如果需要,具体观察者角色可以保存一个指向具体主题角色的引用。

模式的应用场景:

The observer pattern is used when:

the change of a state in one object must be reflected in another object without keeping the objects tight coupled.

the framework we are writing needs to be enhanced in future with new observers with minimal changes.

Some Classical Examples:

Model View Controller Pattern - The observer pattern is used in the model view controller (MVC) architectural pattern. In MVC the this pattern is used to decouple the model from the view. View represents the Observer and the model is the Observable object.

Event management - This is one of the domains where the Observer patterns is extensively used. Swing and .Net are extensively using the Observer pattern for implementing the events mechanism.

一个对象状态的改变必须要要被另一个对象所得知,且这两个对象是解耦的关系。

我们写框架时,考虑到未来可能会增加一些观察者,又想做最小的变更,这时我们使用观察者模式。

MVC模式:观察者模式常被用在MVC模式中。在MVC模式中,观察者模式用于解耦“模型”和“视图”。“视图”代表Observer(观察者),“模型”代表Observable(被观察者)

整件管理器:在这个领域中,观察者也是被用的最多的。Java中的Swing和.Net使用观察者模式实现事件机制。

结构图:



模式的优缺点:

优点:

1、当两个对象之间送耦合,他们依然可以交互,但是不太清楚彼此的细节。观察者模式提供了一种对象设计,让主题和观察者之间送耦合。主题所知道只是一个具体的观察者列表,每一个具体观察者都符合一个抽象观察者的接口。主题并不认识任何一个具体的观察者,它只知道他们都有一个共同的接口。

2、观察者模式支持“广播通信”。主题会向所有的观察者发出通知。

3、观察者模式符合“开闭原则”的要求。

缺点:

1、如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。

2、 如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进 行循环调用,可能导致系统崩溃。

3、观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。

代码:

推模式(Push Model)

package com.lee.desingerPattener23.observer.push;

import java.util.Observable;
import java.util.Observer;

public class PushClient {
public static void main(String[] args) {
NewsPublisher publisher = new NewsPublisher();
//添加观察者对象 addObserver是Observable中的方法
publisher.addObserver(new SubscriberObserver());
publisher.addObserver(new ManagerObserver());
//发布新闻,触发通知事件
publisher.publishNews("Hello news", "news body1");
}
}

/**
* Subject ROLE
* NewsPublisher: news publisher
*
*/

class NewsPublisher extends Observable {

public void publishNews(String newsTitle, String newsBody) {
News news = new News(newsTitle, newsBody);
//通过setChanged()方法标明对象的状态已发生变化
setChanged();
System.out.println("News published:" + newsTitle);
//通知各Observer,并发送一个名为news对象的消息
this.notifyObservers(news);
//other process ... such as save news to database
//.....
}
}

class SubscriberObserver implements Observer {
//这里Observable没有传给Observer,Observable在状态变化时将所有的状态信息都发给observer
public void update(Observable observee, Object param) {
if (param instanceof News) {
mail2Subscriber((News)param);
}
}

private void mail2Subscriber(News news) {
System.out.println("Mail to subscriber. A news published with title:" + news.getTitle());
}
}

class ManagerObserver implements Observer {

public void update(Observable observee, Object param) {
if (param instanceof News) {
mail2Manager((News)param);
}
}

private void mail2Manager(News news) {
System.out.println("Mail to Manager. A news published with title:" + news.getTitle());
}
}

//data entity
class News {
private String title;
private String body;

public News(String title, String body) {
this.title = title;
this.body = body;
}

public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}


拉模式(Pull Model)

package com.lee.desingerPattener23.observer.pull;

import java.util.Observable;
import java.util.Observer;

public class PullClient {
public static void main(String[] args) {
NewsPublisher publisher = new NewsPublisher();
//添加观察者对象 addObserver是Observable中的方法
publisher.addObserver(new SubscriberObserver());
publisher.addObserver(new ManagerObserver());
//发布新闻,触发通知事件
publisher.publishNews("Hello Amcanic news", "news body1");
publisher.publishNews("Hello China news", "news body1");
}
}

/**
* Subject ROLE
* NewsPublisher: news publisher
*
*/

class NewsPublisher extends Observable {
private String newsTitle;
private String newsBody;

public void publishNews(String newsTitle, String newsBody) {
this.newsTitle = newsTitle;
this.newsBody = newsBody;
News news = new News(newsTitle, newsBody);
//通过setChanged()方法标明对象的状态已发生变化
setChanged();
System.out.println("News published:" + newsTitle);
//通知各Observer,并发送一个名为news对象的消息
this.notifyObservers(news);
//other process ... such as save news to database
//.....
}
public String getNewsTitle() {
return newsTitle;
}
public void setNewsTitle(String newsTitle) {
this.newsTitle = newsTitle;
}
public String getNewsBody() {
return newsBody;
}
public void setNewsBody(String newsBody) {
this.newsBody = newsBody;
}

}

class SubscriberObserver implements Observer {
//重点!!!!!
//拉模式中,suject须提供状态信息的get方法,让observer可以获取自己感兴趣的信息。
//个人认为,拉模式中,把Observable传给了Observer,然后Observer决定对哪些信息感兴,从而进行筛选。
public void update(Observable o, Object param) {
if (o instanceof NewsPublisher&¶m instanceof News) {
NewsPublisher n = (NewsPublisher)o;
if(n.getNewsTitle().contains("China")){
mail2Subscriber((News)param);
}
}
}

private void mail2Subscriber(News news) {
System.out.println("Mail to subscriber. A news published with title:" + news.getTitle());
}
}

class ManagerObserver implements Observer {

public void update(Observable o, Object param) {
if (param instanceof News) {
mail2Manager((News)param);
}
}

private void mail2Manager(News news) {
System.out.println("Mail to Manager. A news published with title:" + news.getTitle());
}
}

//data entity
class News {
private String title;
private String body;

public News(String title, String body) {
this.title = title;
this.body = body;
}

public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}


结果:

News published:Hello Amcanic news
Mail to Manager. A news published with title:Hello Amcanic news
News published:Hello China news
Mail to Manager. A news published with title:Hello China news
Mail to subscriber. A news published with title:Hello China news


所有模式:

创建型模式,共五种:工厂方法模式、抽象工厂模式单例模式建造者模式原型模式

结构型模式,共七种:适配器模式装饰器模式代理模式外观模式桥接模式组合模式享元模式

行为型模式,共十一种:策略模式模板方法模式观察者模式迭代子模式责任链模式命令模式备忘录模式状态模式访问者模式中介者模式解释器模式

补充模式:空对象模式

参考/转自:
http://www.oodesign.com/observer-pattern.html http://www.cnblogs.com/mengdd/archive/2013/02/07/2908929.html http://www.cnblogs.com/abcdwxc/archive/2007/09/19/898856.html http://blog.csdn.net/lansuiyun/article/details/11396815 http://blog.chinaunix.net/uid-9288192-id-80329.html
转载请注明:
/article/8544862.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: