1.观察者模式 观察者模式是关于多个对象想知道一个对象中数据变化情况的一种成熟的模式。 观察者模式中有一个称作“主题(被观察)”的对象和若干个称作“观察者”的对象,“主题”和“观察者”间是一种一对多的依赖关系,当“主题”的状态发生变化时,所有“观察者”都得到通知。
2.观察者模式的结构 观察者模式的结构中包含了四种角色: ①主题(Subject):一般情况下主题是一个接口,该接口规定了具体主题需要实现的方法,一般都有添加,删除和更新内容等基本方法,当然可以适当扩充,一般主题也叫做被观察者。 ②观察者(Observer):观察者一般也是一个接口,主要方法为更新内容的接口方法。 ③具体主题(ConcreteSubject):具体主题是实现主题接口类的一个实例,该实例包含有可以经常发生变化的数据。具体主题需使用一个集合,比如ArrayList,存放观察者的引用,以便数据变化时通知具体观察者。 ④具体观察者(ConcreteObserver):具体观察者是实现观察者接口类的一个实例。具体观察者包含有可以存放具体主题引用的主题接口变量,以便具体观察者让具体主题将自己的引用添加到具体主题的集合中,使自己成为它的观察者,或让这个具体主题将自己从具体主题的集合中删除,使自己不再是它的观察者,所以一般观察者的方法里面都有一个删除的接口。
3.观察者模式的优点 ①具体主题和具体观察者是松耦合关系。由于主题接口仅仅依赖于观察者接口,因此具体主题只是知道它的观察者是实现观察者接口的某个类的实例,但不需要知道具体是哪个类。同样,由于观察者仅仅依赖于主题接口,因此具体观察者只是知道它依赖的主题是实现主题接口的某个类的实例,但不需要知道具体是哪个类。 ②观察者模式满足设计模式中的“开-闭原则”。主题接口仅仅依赖于观察者接口,这样,就可以让创建具体主题的类也仅仅是依赖于观察者接口,因此,如果增加新的实现观察者接口的类,不必修改创建具体主题的类的代码。同样,创建具体观察者的类仅仅依赖于主题接口,如果增加新的实现主题接口的类,也不必修改创建具体观察者类的代码。
4.使用场景 ①当一个对象的数据更新时需要通知其他对象,但这个对象又不希望和被通知的那些对象形成紧耦合。 ②当一个对象的数据更新时,这个对象需要让其他对象也各自更新自己的数据,但这个对象不知道具体有多少对象需要更新数据。
5.举例 ①首先定义一个主题接口和一个观察者接口,代码如下: //主题接口 public interface Subject { void registerObserver(Observer o);//增加观察者 void removeObserver(Observer o);//移除观察者 void notifyObservers(float temprature);//通知观察者去更新 }
//观察者接口 public interface Observer { void update(float temprature);//收到通知,开始更新 void remove(Subject mSubject);//不想再观察的时候删除 } ②然后定义实现主题的类和实现抽象观察者的类: public class ConcreteSubject implements Subject { private static final List observers; static { observers = new ArrayList<>(); observers.clear(); } @Override public void registerObserver(Observer o) { observers.add(o); } @Override public void removeObserver(Observer o) { if (observers.indexOf(o) >= 0) { observers.remove(o); } } @Override public void notifyObservers(float temprature) { if (observers.size() <= 0) { System.out.println(“没有观察者”); return; } for (final Observer o : observers) { o.update(temprature); } } } 这个实现了所有的主题接口,方便添加、删除和通知所有的观察者。
具体的观察者如下: public class ConcreteObserver implements Observer { @Override public void update(float temprature) { System.out.println(“温度为:” + temprature); } @Override public void remove(Subject mSubject) { mSubject.removeObserver(this);//在不需要观察的时候删掉即可 } }
|