观察者模式:是指定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,
所有依赖于它的对象都得到通知并被自动更新
在这个定义当中,首先第一个关键词是依赖关系,这是类与类之间关系的一种,依赖是指一个类依赖另一个类,一般是通过形参的方式传递对象在方法中,其二:是怎么做到目标对象通知后观察者自动更新呢? 其实做到这点也不难,就是该类有自动更新方法的所属对象即可做到自动更新,
观察者模块角色包括如下:
Subject:目标
ConcreteSubject:具体目标
Observer:观察者
ConcreteObserver:具体观察者
这样讲可能大家看的不太明白,打个比方:假如猫是老鼠和够的观察对象,老鼠和狗是观察者,而猫是被观察者也就是目标对象,目标对象就一个,但是观察者就可以有多个,猫叫老鼠跑,猫叫狗跑,现在使用观察者模式来写出该代码.
Subject.java 目标对象抽象类,当然也可以写成接口
<pre class="java" name="code">/** * 被观察的目标 有添加 和删除 通知的共有方法 * @author carpool */ public interface Subject { //注册或者叫添加观察者 void resgister(Observer observer); //删除观察者 void delete(Observer observer); //具体目标的行为属性 void cry(); }
具体的目标对象,Cat.java
public class Cat implements Subject { /** * 对外部类提供注册观察者的方法 */ List<Observer> list = new ArrayList<Observer>(); @Override public void resgister(Observer observer) { list.add(observer); } @Override public void delete(Observer observer) { list.remove(observer); } /** * 当猫叫的时候通知 所注册的观察者也就是 * 老鼠和狗要跑 */ @Override public void cry() { for(Observer observer:list){ observer.response(); } } }
Observer.java 观察者抽象类
public interface Observer { void response();//定义观察者自动更新的方法 }
Dog.java 具体的观察者
public class Dog implements Observer { @Override public void response() { System.out.println("猫叫了 通知 狗快跑……"); } }
Mouse.java也是观察者之一
public class Mouse implements Observer { @Override public void response() { System.out.println("猫叫了 通知 老鼠快跑……"); } }
客户端 Client.java负责注册观察者和目标通知
public class Client { public static void main(String[] args) { Cat cat = new Cat();//创建目标对象 Dog dog = new Dog();//创建观察者 Mouse mouse = new Mouse();//创建观察者 cat.resgister(mouse);//注册观察者到目标对象中,一般用集合保存注册的观察者 cat.resgister(dog);//注册观察者到目标对象中,一般用集合保存注册的观察者 cat.cry();//通知目标对象,发生该变了,然后观察者自动更新 } }
打印结果:
猫叫了 通知 老鼠快跑…… 猫叫了 通知 狗快跑……
从打印的结果看,和注册观察者对象的顺序一致,
现在有个需求是这样的,当观察者更新的时候判断下用户的某个行为,比如目标对象是否登录了,如果目标对象登录了才更新,加了一个这样的需求,
分析:结合上面的例子看
@Override public void response() { System.out.println("猫叫了 通知 狗快跑……"); }
这是更新的方法,但是要判断目标对象的登录是否,就必须持有目标对象才能更新,那么要么是通过参数传递进去,要么是通过构造函数实现,
一:通过构造函数方式实现:
Subject.java
/** * 被观察的目标 有添加 和删除 通知的共有方法 * @author carpool */ public interface Subject { //注册或者叫添加观察者 void resgister(Observer observer); //删除观察者 void delete(Observer observer); //具体目标的行为属性 void cry(); }
Cat.java
public class Cat implements Subject { /** * 对外部类提供注册观察者的方法 */ List<Observer> list = new ArrayList<Observer>(); @Override public void resgister(Observer observer) { list.add(observer); } @Override public void delete(Observer observer) { list.remove(observer); } /** * 当猫叫的时候通知 所注册的观察者也就是 * 老鼠和狗要跑 */ @Override public void cry() { for(Observer observer:list){ observer.response(); } } /** * 登陆 * @return */ public boolean login(){ return true; } }
Observer.java
public interface Observer { void response();//定义观察者自动更新的方法 }
Dog.java
public class Dog implements Observer { public Cat cat; public Dog(Cat cat) { this.cat = cat; } @Override public void response() { if(cat.login()){ System.out.println("猫叫了 通知 狗快跑……"); } } }
Mouse.java
public class Mouse implements Observer { public Cat cat; public Mouse(Cat cat) { this.cat = cat; } @Override public void response() { if(cat.login()){ System.out.println("猫叫了 通知 老鼠快跑……"); } } }
Client.jav
public class Client { public static void main(String[] args) { Cat cat = new Cat();//创建目标对象 Dog dog = new Dog(cat);//创建观察者 Mouse mouse = new Mouse(cat);//创建观察者 cat.resgister(mouse);//注册观察者到目标对象中,一般用集合保存注册的观察者 cat.resgister(dog);//注册观察者到目标对象中,一般用集合保存注册的观察者 cat.cry();//通知目标对象,发生该变了,然后观察者自动更新 } }
打印结果:
猫叫了 通知 老鼠快跑…… 猫叫了 通知 狗快跑……
二:是通过形式传递方式如下:
public interface Observer { void response(Subject subject);//定义观察者自动更新的方法 }
但是在jdk中sun公司其实帮我们实现了观察者模式,我们只要实现其暴露出来的接口就行,
观察者模块的优点:
在于可以实现表示层和数据逻辑层的分离,并在观察目标和观察者之间建立了一个抽象的耦合,支持广播通信,
缺点:当观察者很多时,会消耗很多时间去通知观察者更新!