这是我第一次写那么具体的博客,出错了勿笑,还请指出。
观察者模式
观察者模式定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,他的所有依赖者都会收到通知并自动更新。观察者模式中的被观察者就是一,多个依赖者就是观察者。如下图:
就象我们很小的时候一家人其乐融融,聊着家常的时候,会有一个人逗你,你会根据他的行为做出各种反应。你的家人会根据你的反应做出各种反应。这就是观察者模式的一种体现,其中,逗你的人是被观察者(被你观察),你是观察者;根据你的反应做出各种行为的家人是观察者(观察你),你又是被观察者。所以,观察者也可以是被观察者。
利用观察者模式,被观察者/可观察者是具有状态的对象,并且可以控制这些状态。也就是说,有“一个”具有状态的对象。另一方面,观察者使用这些状态,虽然这些状态并不属于他们,有许多的观察者,依赖被观察者/可观察者来告诉他们状态何时改变了。这就产生一个关系:“一个”被观察者/可观察者对“多个”观察者的关系。因为被观察者/可观察者是真正拥有数据的对象,观察者是被观察者/可观察者的依赖者,在数据变化更新时,这样比起让许多对象控制同一份数据来,可以得到更干净的OO设计。
观察者模式类图:
当两个对象之间松耦合,它们依然可以交互,但是不太清除彼此的细节。
观察者模式提供了这一种对象设计,让被观察者/可观察者和观察者之间松耦合。
看到上面的图,你就会明白了吧。
关于观察者的一切,被观察者/可观察者只知道观察者实现了某个接口(也就是Observer)。主题不需要知道观察者的具体类是谁、做了些什么或者其他任何细节。
任何时候我们都可以增加新的观察者。因为被观察者/可观察者唯一依赖的东西是一个实现Observer接口的对象列表,所以我们可以随时增加新观察者。事实上,在运行时我们可以用新的观察者取代现有的观察者,被观察者/可观察者不会受到任何影响。同样的也可以在任何时候删除某些观察者。
在新类型的观察者出现时,被观察者/可观察者的代码不需要修改。假如我们有个新的具体类需要当观察者,我们不需要为了兼容新类型而修改被观察者/可观察者的代码,所有要做的就是在新的类里实现此观察者接口,然后注册通过方法regiserObserver()为观察者即可。观察者/可观察者不在乎别的,它只会通过方法notifyObserver()发生通知给所有实现了观察者接口的对象。
我们可以独立地复用被观察者/可观察者或者观察者,如果我们在其他地方需要使用被观察者或者观察者,可以轻易地复用,因为二者并非紧耦合。
当然,在被观察者/可观察者的状态更新时,被观察者/可观察者可以通过推的方法(直接向观察者实现的update()方法中传递数据)向观察者中传递数据,也可以通过拉的方式(被观察者/可观察者通过观察者实现的update()方法通知观察者我的数据改变了,观察者根据自己的需要通过被观察者/可观察者的getState()方法获取自己需要的数据)方式传递数据给观察者。这两种方法在具体的情况下各有利弊,需要根据具体要求选择。
下面通过具体例子来解释下:
在一家人其乐融融的聊天时,大家突然注意到在旁边玩耍的幼小的你,这时候你就是被观察者/可观察者,你的家人就是观察者。
//被观察者/可观察者接口
interface Observabel{
void registerObserver(Observer observer);
void removeObserver(Observer observer);
void notifyObserver();
}
//观察者接口
interface Observer{
//当被观察者/可观察者状态改变时调用
void update(String str);
}
//被观察者/可观察者具体实现(一个child)
class Child implements Observable{
private ArrayList<Observer> mObservers;
public Child(){
//初始化观察者队列,用于管理观察者
mObservers = new ArrayList<Observer>();
}
//注册观察者方法
@Override
public void registerObserver(Observer observer){
mObserver.add(observer);
}
//撤销观察者方法
@Override
public void removeObserver(Observer observer){
int index = mObserver.indexOf(observer);
if(index > 0){
mObserver.remove(observer);
}
}
//通知观察者,被观察者/可观察者状态改变的方法
//并且使用推的方式,直接将状态数据传递给观察者update()方法
@Override
public void notifyObserver(String str){
for(int i = 0; i < mObservers.getSize(); i ++){
Observer o = (Observer)mObservers.get(i);
o.update(str);
}
}
}
//一个观察者(孩子的父亲)
class ChildFather implements Observer{
private Observable mObservable;
//在构造方法中注册观察者
public ChildFather(){
mObservable = new Child();
mObservable.rigesterObserver(this);
}
//被观察/可观察者状态更新时,观察者根据这个方法做出具体的响应
@Override
public void update(String str){
if(str.equal(“拍手并且张嘴呵呵的笑”)){
System.out.println(“呵呵”);
}else if(str.equal(“摇摇晃晃的向前走”)){
System.out.println(“呵呵”);
}else if(str.equal(“牙牙学语,嘴里喊着“妈妈,妈妈···””)){
System.out.println(“快喊一声爸爸来听听”);
}
}
}
//一个观察者(孩子的妈妈)
class ChildMother implements Observer{
private Observable mObservable;
//在构造方法中注册观察者
public ChildMother (){
mObservable = new Child();
mObservable.rigesterObserver(this);
}
//被观察/可观察者状态更新时,观察者根据这个方法做出具体的响应
@Override
public void update(String str){
if(str.equal(“拍手并且张嘴呵呵的笑”)){
System.out.println(“看你高兴的”);
}else if(str.equal(“摇摇晃晃的向前走”)){
System.out.println(“慢着,别摔着了”);
}else if(str.equal(“牙牙学语,嘴里喊着“妈妈,妈妈···””)){
System.out.println(“真乖”);
}
}
}
//一个观察者(其他人)
class ChildOther implements Observer{
private Observable mObservable;
//在构造方法中注册观察者
public ChildMother (){
mObservable = new Child();
mObservable.rigesterObserver(this);
}
//被观察/可观察者状态更新时,观察者根据这个方法做出具体的响应
@Override
public void update(String str){
if(str.equal(“拍手并且张嘴呵呵的笑”)){
System.out.println(“你看他,一点儿也不认生”);
}else if(str.equal(“摇摇晃晃的向前走”)){
System.out.println(“真聪明,都学会走步了”);
}else if(str.equal(“牙牙学语,嘴里喊着“妈妈,妈妈···””)){
System.out.println(“会喊妈妈了,呵呵”);
}
}
}
public class Main{
public static void main(string[] arg){
//被观察者/可观察者对象
Child child = new Child();
//观察者对象(父亲)
Observer father = new ChildFather();
//观察者对象(母亲)
Observer mother = new ChildMother();
//观察者对象(其他人)
Observer other = new ChildOther();
//被观察者/可观察者状态改变,并通知所有的观察者它的状态改变了
child.notifyObsever(“拍手并且张嘴呵呵的笑”);
child.notifyObserver(“摇摇晃晃的向前走”);
child.notifyObserver(“牙牙学语,嘴里喊着“妈妈,妈妈···””);
}
}