@@@模式定义:
定义对象间的一种一对多的依赖关系。当一个对象的状态发生改变时,
所有依赖于它的对象都得到通知并被自动更新。
观察者模式又被称为发布——订阅模式。
@@@练习示例:
订阅报纸
@@@示例代码:
\src\pattern\Subject.java
\src\pattern\Observer.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\src\pattern\NewsPaper.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\src\pattern\Reader.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\src\user\Client.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[---使用JAVA自带的观察者模式---]
\src\pattern\NewsBook.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\src\pattern\BookReader.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\src\user\BookClient.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@@模式的实现:
1) 目标和观察者之间一般是一对多,也可以一对一;
2) 观察者可以观察多个目标,一般需要为每个目标定义不同的回调方法而不是在update方法中来区分;
3) 观察者模式有推模型和拉模型两种方式;
@@@模式的优点:
1) 观察者模式实现了观察者和目标对象之间的抽象耦合;
2) 观察者模式实现了动态联动;
3) 观察者模式支持广播通信;
@@@模式的缺点:
1) 可能会引起无谓的操作;
@@@模式的本质:
触发联动
@@@模式体现的设计原则:
NA
定义对象间的一种一对多的依赖关系。当一个对象的状态发生改变时,
所有依赖于它的对象都得到通知并被自动更新。
观察者模式又被称为发布——订阅模式。
@@@练习示例:
订阅报纸
@@@示例代码:
\src\pattern\Subject.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
package pattern;
import java.util.ArrayList;
import java.util.List;
/**
* 目标对象,作为被观察者
*/
public class Subject {
/**
* 用来保存注册的观察者对象,也就是报纸的订阅者
*/
private List<Observer> readers = new ArrayList<Observer>();
/**
* 报纸的读者需要向报社订阅,先要注册
* @param reader 报纸的读者
*/
public void attach(Observer reader) {
readers.add(reader);
}
/**
* 报纸的读者可以取消订阅
* @param reader 报纸的读者
*/
public void detach(Observer reader) {
readers.remove(reader);
}
/**
* 当每期报纸印刷出来后,就要迅速主动地被送到读者的手中
* 相当于通知读者,让他们知道
*/
protected void notifyObservers() {
for (Observer reader : readers) {
reader.update(this);
}
}
}
\src\pattern\Observer.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
package pattern;
/**
* 观察者,比如报纸的读者
*/
public interface Observer {
/**
* 被通知的方法
* @param subject 具体的目标对象,可以获取报纸的内容
*/
public void update(Subject subject);
}
\src\pattern\NewsPaper.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
package pattern;
/**
* 报纸对象,具体的目标对象
*/
public class NewsPaper extends Subject {
/**
* 报纸的具体内容
*/
private String content;
/**
* 获取报纸的具体内容
* @return 报纸的具体内容
*/
public String getContent() {
return content;
}
/**
* 示意,设置报纸的具体内容,相当于要出版报纸了
* @param content 报纸的具体内容
*/
public void setContent(String content) {
this.content = content;
// 内容有了,说明又出版报纸了,那就通知所有的读者
notifyObservers();
}
}
\src\pattern\Reader.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
package pattern;
/**
* 真正的读者,为了简单就描述一下姓名
*/
public class Reader implements Observer {
/**
* 读者的姓名
*/
private String name;
@Override
public void update(Subject subject) {
// 这里采用拉的方式
System.out.println(name + "收到报纸了,阅读它,内容是:"
+ ((NewsPaper)subject).getContent());
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
\src\user\Client.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
package user;
import pattern.NewsPaper;
import pattern.Reader;
public class Client {
public static void main(String[] args) {
// 创建一份报纸,作为被观察者
NewsPaper subject = new NewsPaper();
// 创建读者,也就是观察者
Reader reader1 = new Reader();
reader1.setName("张三");
Reader reader2 = new Reader();
reader2.setName("李四");
Reader reader3 = new Reader();
reader3.setName("王五");
// 注册读者
subject.attach(reader1);
subject.attach(reader2);
subject.attach(reader3);
// 出版报纸
subject.setContent("本期的内容是观察者模式");
}
}
[---使用JAVA自带的观察者模式---]
\src\pattern\NewsBook.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
package pattern;
/**
* 报纸对象,具体的目标实现
*/
public class NewsBook extends java.util.Observable {
/**
* 报纸的具体内容
*/
private String content;
/**
* 获取报纸的具体内容
* @return 报纸的具体内容
*/
public String getContent() {
return content;
}
/**
* 示意,设置报纸的具体内容,相当于要出版报纸了
* @param content 报纸的具体内容
*/
public void setContent(String content) {
this.content = content;
// 内容有了,说明又出版报纸了,那就通知所有的读者
// 注意在使用Java中的Observer模式的时候,下面这句话不可少
this.setChanged();
// 然后主动通知,这里用的是推的方式
this.notifyObservers(this.content);
// 如果用拉的方式,这么调用
// this.notifyObservers();
}
}
\src\pattern\BookReader.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
package pattern;
import java.util.Observable;
/**
* 真正的读者,为了简单就描述一下姓名
*/
public class BookReader implements java.util.Observer {
/**
* 读者的姓名
*/
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public void update(Observable o, Object obj) {
// 这里采用推的方式
System.out.println(name + "收到报纸了,阅读它,目标推过来的内容是:"
+ obj);
// 这里获取拉的数据
System.out.println(name + "收到报纸了,阅读它,主动到目标对象去拉的内容是:"
+ ((NewsBook)o).getContent());
}
}
\src\user\BookClient.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
package user;
import pattern.BookReader;
import pattern.NewsBook;
public class BookClient {
public static void main(String[] args) {
// 创建一份报纸,作为被观察者
NewsBook subject = new NewsBook();
// 创建读者,也就是观察者
BookReader reader1 = new BookReader();
reader1.setName("张三");
BookReader reader2 = new BookReader();
reader2.setName("李四");
BookReader reader3 = new BookReader();
reader3.setName("王五");
// 注册读者
subject.addObserver(reader1);
subject.addObserver(reader2);
subject.addObserver(reader3);
// 出版报纸
subject.setContent("本期的内容是观察者模式");
}
}
@@@模式的实现:
1) 目标和观察者之间一般是一对多,也可以一对一;
2) 观察者可以观察多个目标,一般需要为每个目标定义不同的回调方法而不是在update方法中来区分;
3) 观察者模式有推模型和拉模型两种方式;
@@@模式的优点:
1) 观察者模式实现了观察者和目标对象之间的抽象耦合;
2) 观察者模式实现了动态联动;
3) 观察者模式支持广播通信;
@@@模式的缺点:
1) 可能会引起无谓的操作;
@@@模式的本质:
触发联动
@@@模式体现的设计原则:
NA