观察者模式:是指定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,
所有依赖于它的对象都得到通知并被自动更新
在这个定义当中,首先第一个关键词是依赖关系,这是类与类之间关系的一种,依赖是指一个类依赖另一个类,一般是通过形参的方式传递对象在方法中,其二:是怎么做到目标对象通知后观察者自动更新呢? 其实做到这点也不难,就是该类有自动更新方法的所属对象即可做到自动更新,
观察者模块角色包括如下:
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公司其实帮我们实现了观察者模式,我们只要实现其暴露出来的接口就行,
观察者模块的优点:
在于可以实现表示层和数据逻辑层的分离,并在观察目标和观察者之间建立了一个抽象的耦合,支持广播通信,
缺点:当观察者很多时,会消耗很多时间去通知观察者更新!