今天学习了一下观察者模式,做一下总结。
什么是观察者模式?
观察者模式:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知并被自动更新。
观察者模式也叫“依赖”或者“发布——订阅”模式。举一些例子来说明什么是观察者模式。
比如订阅者与报刊之间就属于目标(subject)与观察者(observer)关系。每一个订阅者相当于一个观察者,而这些观察者是依赖于出版社的,当出版社的状态发生改变时即就是有新的期刊时,所有依赖于它的订阅者将得到通知,并会收到最新的报刊。
再比如我们程序中例子,数据与界面之间的关系。一个表格对象和一个柱状图对象可以使用不同的表现形式描述同一一个应用的数据对象的信息。当数据对象的信息改变时,这些界面里的数据也将会得到改变。而表格对象与柱状图对象是没有依赖关系的。
观察者模式的参与者:
- Subject(目标)
目标知道它的观察者,但是不知道具体是谁。可以有任意多个观察者观察同一个目标。
提供注册和删除观察对象的接口 - Observer(观察者)
为那些在目标发生改变时需要获得通知的对象定义一个更新接口。 - ConcreteSubject(具体目标)
将有关状态存入各ConcretSubject对象
当它的状态发生改变时,向他的各个观察者发出通知。 - ConcreteObserver(具体观察者)
维护一个指向ConcreteSubjec对象的引用。
存储有关状态,将这些状态与目标的状态保持一致
实现Observer的更新接口以使自身状态与目标的状态保持一致。
为什么要使用观察者模式?
将一个系统分割成一些列相互协作的类时有一个副作用:需要维护相关对象间的一致性。而这个时候,维护他们之间的一致性是非常不容易的,因为他们之间紧密耦合,相互依赖,这样重用性降低。而观察者模式是松耦合的,因此重用性会得到提高。
什么时候使用观察者模式?
- 当一个对象模型有两个方面,其中一个方面依赖于另一个方面。将这二者封装在独立的对象中以使他们可以各自独立的改变和复用。
- 当对一个对象的改变需要同时改变其他对象,而不知道具体有多少对象有待改变。
- 当一个对象必须通知其他对象,而他又不能假定其他对象是谁。也就是说,我们不希望这些对象是紧密耦合。
如何使用观察者模式?
下面通过一个示例来说明。
/*
* 出版社的抽象接口
*/
public interface Subject {
//移除观察者
public void removeObserver(Observer o);
//添加观察者
public void addObserver(Observer o);
//通知观察者
public void notifyObservers();
}
/*
* 具体的目标对象 这里假定为“读者出版社”
*/
public class ConcreteSubject implements Subject{
private ArrayList<Observer> observers;
private String book;
public ConcreteSubject() {
observers = new ArrayList<Observer>();
}
@Override
public void removeObserver(Observer o) {
int i= observers.indexOf(o);
if(i>=0) {
observers.remove(i);
}
}
@Override
public void addObserver(Observer o) {
observers.add(o);
}
@Override
public void notifyObservers() {
for(int i=0;i<observers.size();i++) {
observers.get(i).update(book);
}
}
//设置状态信息的改变方法 当有新书时 可通过此方法进行添加
public void setState(String book) {
this.book = book;
}
//通过此方法 订阅者(observer)可以主动得到目标(subject)中的书
public String getState() {
return book;
}
}
/*
* 观察者的抽象接口,拥有一个update()方法 当目标(subject)状态改变时 调用此方法
*/
public interface Observer {
public void update(String book);
}
/*
* 订阅者共有的接口 张三和李四订阅者都必须实现这个接口 因为他们有共同的方法display
*/
public interface DisplayElement {
public void display();
}
/*
* 订阅者 李四
*/
public class Observer1 implements Observer,DisplayElement{
private Subject subject;
private String book;
public Observer1(Subject subject) {
this.subject = subject;
subject.addObserver(this);
}
@Override
public void update(String book) {
this.book = book;
display();
}
@Override
public void display() {
System.out.println("Observer1 收到了一本新书:"+book);
}
}
/*
* 订阅者 张三
*/
public class Observer2 implements Observer,DisplayElement{
private String book;
private Subject subject;
public Observer2(Subject subject) {
this.subject = subject;
subject.addObserver(this);
}
@Override
public void update(String book) {
this.book = book;
display();
}
@Override
public void display() {
System.out.println("observer2 收到了一本新书:"+book);
}
}
public class ObserverTest {
public static void main(String[] args) {
ConcreteSubject subject = new ConcreteSubject();
Observer1 zhangsan = new Observer1(subject);
Observer2 lisi = new Observer2(subject);
subject.setState("读者第一刊");
subject.notifyObservers();
}
}