深入浅出设计模式之观察者模式
观察者(Observer)模式又名发布-订阅(Publish/Subscribe)模式。GOF给观察者模式如下定义:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
在这里先讲一下面向对象设计的一个重要原则——单一职责原则。因此系统的每个对象应该将重点放在问题域中的离散抽象上。因此理想的情况下,一个对象只做一件事情。这样在开发中也就带来了诸多的好处:提供了重用性和维护性,也是进行重构的良好的基础。
因此几乎所有的设计模式都是基于这个基本的设计原则来的。观察者模式的起源我觉得应该是在GUI和业务数据的处理上,因为现在绝大多数讲解观察者模式的例子都是这一题材。但是观察者模式的应用决不仅限于此一方面。
下面我们就来看看观察者模式的组成部分。
1) 抽象目标角色(Subject):目标角色知道它的观察者,可以有任意多个观察者观察同一个目标。并且提供注册和删除观察者对象的接口。目标角色往往由抽象类或者接口来实现。
2) 抽象观察者角色(Observer):为那些在目标发生改变时需要获得通知的对象定义一个更新接口。抽象观察者角色主要由抽象类或者接口来实现。
3) 具体目标角色(Concrete Subject):将有关状态存入各个Concrete Observer对象。当它的状态发生改变时, 向它的各个观察者发出通知。
4) 具体观察者角色(Concrete Observer):存储有关状态,这些状态应与目标的状态保持一致。实现Observer的更新接口以使自身状态与目标的状态保持一致。在本角色内也可以维护一个指向Concrete Subject对象的引用。
可以看得出来,在Subject这个抽象类中,提供了上面提到的功能,而且存在一个通知方法:notify。这样当具体目标角色的状态发生改变,按照约定则会去调用通知方法,在这个方法中则会根据目标角色中注册的观察者名单来逐个调用相应的update方法来调整观察者的状态。这样观察者模式就走完了一个流程。
在下面的例子中会更深刻的体验到这个流程的。
public interface IObserver {
//监听事件发生后的动作
public void update();
}
//具体观察者
public class Observer1 implements IObserver {
public void update() {
System.out.println("Observer1 update!");
}
}
//具体观察者
public class Observer2 implements IObserver {
public void update() {
System.out.println("Observer2 update!");
}
}
//目标对象
public class Subject {
//观察者数组
private List<IObserver> observers = new ArrayList<IObserver>();
//通知观察者
public void notifyObservers()
{
for(IObserver observer:observers)
{
observer.update();
}
}
//添加观察者
public void AddOberver(IObserver observer)
{
observers.add(observer);
}
//触发观察者动作的事件
public void Do()
{
System.out.println("Subject do!");
//通知观察者
notifyObservers();
}
}
public class ObeserverTest {
public static void main(String[] args) {
Subject s=new Subject();
Observer1 observer1=new Observer1();
Observer2 observer2=new Observer2();
s.AddOberver(observer1);
s.AddOberver(observer2);
s.Do();
}
}
结果:
Subject do!
Observer1 update!
Observer2 update!
GOF给出了以下使用观察者模式的情况:
1) 当一个抽象模型有两个方面, 其中一个方面依赖于另一方面。将这二者封装在独立的对象中以使它们可以各自独立地改变和复用。
2) 当对一个对象的改变需要同时改变其它对象, 而不知道具体有多少对象有待改变。
3) 当一个对象必须通知其它对象,而它又不能假定其它对象是谁。换言之, 你不希望这些对象是紧密耦合的。
其实观察者模式同桥梁、策略有着共同的使用环境:将变化独立封装起来,以达到最大的重用和解耦。观察者与后两者不同的地方在于,观察者模式中的目标和观察者的变化不是独立的,而是有着某些联系。