什么是观察者模式?
当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知它的依赖对象。观察者模式属于行为型模式。
应用场景:
一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知,进行广播通知。
解释说明:
1、拍卖的时候,拍卖师观察最高标价,然后通知给其他竞价者竞价。
何时使用(一对多):
- 一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这些方面封装在独立的对象中使它们可以各自独立地改变和复用。
- 一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变,可以降低对象之间的耦合度。
- 一个对象必须通知其他对象,而并不知道这些对象是谁。
- 需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象……,可以使用观察者模式创建一种链式触发机制。
上代码(下图是代码架构):
代码:
这个是抽象类Observer:
// Observer抽象类,扩展了实体Observer的实体类
public abstract class Observer {
// 把一个类放进抽象类中意义:其实与普通类中放进去道理一样
public Subject subject;
// 定义抽象类,由实现类实现
public abstract void update();
}
下面这个是subject类:发布者与观察者之间的桥梁
public class Subject {
private List<Observer> observers = new ArrayList<Observer>();
private int state;
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
// 通知所有的观察者,调用notifyall()方法
notifyAllObservers();
}
public void add(Observer observer) {
observers.add(observer);
}
public void notifyAllObservers() {
for (Observer observer : observers) {
// 更新每一个观察者查看的信息
observer.update();
}
}
}
下面这个是观察者(1):
public class OctalObserver extends Observer {
public OctalObserver(Subject subject) {
this.subject = subject;
this.subject.add(this);
}
@Override
public void update() {
System.out.println("Octal String: "
+ Integer.toOctalString(subject.getState()));
}
}
下面这个是观察者(2):
public class HexaObserver extends Observer {
public HexaObserver(Subject subject) {
this.subject = subject;
this.subject.add(this);
}
@Override
public void update() {
System.out.println("Hex String: "
+ Integer.toHexString(subject.getState()).toUpperCase());
}
}
接下来是发布者:
public class ObserverPatternDemo {
public static void main(String[] args) {
Subject subject = new Subject();
new HexaObserver(subject);
new OctalObserver(subject);
new BinaryObserver(subject);
System.out.println("First state change: 15");
subject.setState(15);
System.out.println("Second state change: 10");
subject.setState(10);
}
}
知识点总结:
其实在观察者模式中,主要采用的技术也就是利用抽象类去实现的Java类的扩展;
抽象类特点
(1)抽象类继承子类里面有明确的方法覆写要求,而普通类可以有选择性的来决定是否需要覆写;
(2)抽象类实际上就比普通类多了一些抽象方法而已,其他组成部分和普通类完全一样;
(3)普通类对象可以直接实例化,但抽象类的对象必须经过向上转型之后才可以得到。
注意:虽然一个类的子类可以去继承任意的一个普通类,可是从开发的实际要求来讲,普通类尽量不要去继承另外一个普通类,而是去继承抽象类。
还有值得庆幸的是,Java API 有内置的观察者模式:Java util package 包含最基本的Oberver 和Observerable 类,它们两个之间的关系就是Subject与Observer接口类似。并且许多功能都已经实现好了,我们只需要 push 和 pull 就行了;
经验吸取:
在我们拉数据之前,我们可以设置一个"setChanged()"方法,好让notifyObservers()知道它被调用时应该更新观察者,如果调用notifyObsservers()之前,首先调用setChanged()方法,观察就不会被通知,让我们看看setChanged()方法,
其实对于Java.util.Observable 提供的,这个也有弊端:
(1)它是一个类,并不是一个接口,更糟糕的是,它没有试下你一个接口,限制了它的很多复用,必须设计一个类去继承它,如果某类想要多也想继承它,就陷入了两难的境地,因为Java不支持多重继承的能力;
(2)还有就是ObsercableAPI,setChanged()方法已经被保护起来了,被定义成了Protected:除非你继承它,否则你是五发封装组合到自己的对象中来,这个设计就违反了第二个原则:“多用组合,少用继承”。