当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知它的依赖对象。观察者模式属于行为型模式。
参与者有:
- 被观察者(Subject):知道它的通知对象,事件发生后会通知所有它知道的对象,提供添加删除观察者的接口。
- 观察者(Observer):提供通知后的更新事件
- 具体被观察者(ConcreteSubject):被观察者具体的实例,存储观察者感兴趣的状态。
- 具体观察者(ConcreteObserver):观察者的具体实现。
在软件系统中经常会有这样的需求:如果一个对象的状态发生改变,某些与它相关的对象也要随之做出相应的变化。比如说邮件系统,你在收到一封邮件的时候经常桌面上会有通知,告诉你有邮件收到了。再比如,我们要设计一个自动部署的功能,就像eclipse开发时,只要修改了文件,eclipse就会自动将修改的文件部署到服务器中。 观察者模式有个特点:那就是一个对象要时刻监听着另一个对象,只要它的状态一发生改变,自己随之要做出相应的行动。
用 Java 代码表示:
被观察者类:
import java.util.ArrayList;
abstract class Subject {
private ArrayList<Observer> observers;
public Subject() {
observers = new ArrayList<>();
}
public void attach(Observer observer) {
observers.add(observer);
}
public void detach(Observer observer) {
observers.remove(observer);
}
public void notifyObserver(int state) {
for(Observer o: observers) {
o.update(state);
}
}
}
class ConcreteSubject extends Subject {
private int subjectState;
public int getState() {
return subjectState;
}
public void setState(int newState) {
subjectState = newState;
System.out.println("subject' state change to " + newState);
this.notifyObserver(subjectState);
}
}
观察者类:
interface Observer {
public void update(int state);
}
class ConcreteObserver1 implements Observer {
public void update(int state) {
System.out.println("ConcreteObserver1 know state had changed to " + state);
doSomething();
}
private void doSomething() {
System.out.println("ConcreteObserver1 do something!!!");
}
}
class ConcreteObserver2 implements Observer {
public void update(int state) {
System.out.println("ConcreteObserver2 know state had changed to " + state);
doSomething();
}
private void doSomething() {
System.out.println("ConcreteObserver2 do something!!!");
}
}
class ConcreteObserver3 implements Observer {
public void update(int state) {
System.out.println("ConcreteObserver3 know state had changed to " + state);
doSomething();
}
private void doSomething() {
System.out.println("ConcreteObserver3 do something!!!");
}
}
客户端调用:
class Client {
public static void main(String[] args) {
ConcreteSubject subject = new ConcreteSubject();
Observer o1 = new ConcreteObserver1();
Observer o2 = new ConcreteObserver2();
Observer o3 = new ConcreteObserver3();
subject.attach(o1);
subject.attach(o2);
subject.attach(o3);
subject.setState(11);
subject.detach(o2);
subject.setState(12);
}
}
运行结果:
观察者模式不难,即一个对象的变化会通知其他对象,其他对象对其改变作出响应的处理。
观察者模式适用于:
- 当一个对象在不知道对方具体是如何实现时需要通知其它对象
- 当一个对象改变需要通知不确定数的对象时
观察者模式的优点:
观察者与被观察者之间是属于轻度的关联关系,并且是抽象耦合的,这样,对于两者来说都比较容易进行扩展。
观察者模式是一种常用的触发机制,它形成一条触发链,依次对各个观察者的方法进行处理。但同时,这也算是观察者模式一个缺点,由于是链式触发,当观察者比较多的时候,性能问题是比较令人担忧的。并且,在链式结构中,比较容易出现循环引用的错误,造成系统假死。
考虑下面这样的场景:你被要求开发一个简单的股票监控应用程序。初始要求是:
- 股票有一个符号名称和当前价格。
- 投资者可以监控它的当前价值股票。
- 当股票价格变化时,所有监测的股票投资者都被告知变化。
根据上面的例子,很容易可以写出以下的代码:
股票类:
import java.util.Vector;
abstract class Stock{
private Vector<Investor> investors = new Vector<Investor>();
protected int price = 0;
public void addInvestor(Investor i){
this.investors.add(i);
}
public void delInvestor(Investor i){
this.investors.remove(i);
}
protected void notifyInvestors(int price){
System.out.println("begin to notify the investors.");
for(Investor i:investors){
i.update(price);
}
};
public abstract void setPrice(int price);
}
class TxStock extends Stock{
public void setPrice(int price){
System.out.println("change price.");
this.price = price;
this.notifyInvestors(price);
}
}
投资者类:
interface Investor{
public void update(int price);
}
class BeijingInvestor implements Investor{
private String name;
public BeijingInvestor(String name){
this.name = name;
}
public void update(int price){
System.out.println("Beijing Investor " + this.getName() + " know the stock change to " + price);
}
public String getName(){
return this.name;
}
}
class ShenyangInvestor implements Investor{
private String name;
public ShenyangInvestor(String name){
this.name = name;
}
public void update(int price){
System.out.println("Shenyang Investor " + this.getName() + " know the stock change to " + price);
}
public String getName(){
return name;
}
}
客户端调用:
class Client{
public static void main(String[] args){
Stock stock = new TxStock();
stock.addInvestor(new BeijingInvestor("Lindz"));
stock.addInvestor(new ShenyangInvestor("Xun"));
stock.setPrice(19);
stock.setPrice(25);
}
}
运行结果:
作者:林东洲 链接:https://zhuanlan.zhihu.com/p/25045567 来源:知乎 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。