观察者模式
观察者模式(Observeror or Publish/subscribe)是设计模式中常用的一种。在此种模式中,一个目标对象管理所有相依于它的观察者对象,并且在它本身的状态改变时主动发出通知。通常通过呼叫各观察者所提供的方法来实现。此种模式通常被用来实时事件处理系统。
观察者模式定义了对象间的一种一对多依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使他们能够自动更新自己。
它将观察者和被观察者的对象分离开。提高了应用程序的可维护性和重用性。
结构示意图
代码举例
public interface Observer
{
public void update(float temprature);
}
public class ConcreteObserver implements Observer
{
private float temperature;
private final Subject subject;
public ConcreteObserver(final Subject subject)
{
this.subject = subject;
this.subject.registerObserver(this);
}
public float getTemperature()
{
return temperature;
}
public void setTemperature(final float temperature)
{
this.temperature = temperature;
}
@Override
public void update(final float temperature)
{
this.temperature = temperature;
}
}
public interface Subject
{
public void registerObserver(Observer o);
public void removeObserver(Observer o);
public void notifyObservers();
}
public class ConcreteSubject implements Subject
{
private final List<Observer> observers;
private float temperature;
public float getTemperature()
{
return temperature;
}
private void temperatureChanged()
{
this.notifyObservers();
}
public void setTemperature(final float temperature)
{
this.temperature = temperature;
this.temperatureChanged();
}
public ConcreteSubject()
{
observers = new ArrayList<Observer>();
}
@Override
public void registerObserver(final Observer o)
{
observers.add(o);
}
@Override
public void removeObserver(final Observer o)
{
if (observers.indexOf(o) >= 0)
{
observers.remove(o);
}
}
@Override
public void notifyObservers()
{
for (final Observer o : observers)
{
o.update(temperature);
}
}
}
public class Client
{
public static void main(final String[] args)
{
final ConcreteSubject sb = new ConcreteSubject();
sb.setTemperature((float) 20.00);
final Observer o = new ConcreteObserver(sb);
sb.setTemperature((float) 21.00);
}
}
适用场景
1、对一个对象状态的更新,需要其他对象同步更新,而且其他对象的数量动态可变。
2、对象仅需要将自己的更新通知给其他对象而不需要知道其他对象的细节。
优点
1、Subject和Observer之间是松偶合的,分别可以各自独立改变。
2、Subject在发送广播通知的时候,无须指定具体的Observer,Observer可以自己决定是否要订阅Subject的通知。
缺点
1、松偶合导致代码关系不明显,有时可能难以理解。
2、如果一个Subject被大量Observer订阅的话,在广播通知的时候可能会有效率问题。