观察者模式
观察者模式(有时又被称为模型(Model)-视图(View)模式、源-收听者(Listener)模式或从属者模式)是软件设计模式的一种。
在此种模式中,一个目标物件管理所有相依于它的观察者物件,并且在它本身的状态改变时主动发出通知。
这通常透过呼叫各观察者所提供的方法来实现。此种模式通常被用来实现事件处理系统。
当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知它的依赖对象。观察者模式属于行为型模式。
使用:
一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这些方面封装在独立的对象中使它们可以各自独立地改变和复用。
一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变,可以降低对象之间的耦合度。
一个对象必须通知其他对象,而并不知道这些对象是谁。
需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象……,可以使用观察者模式创建一种链式触发机制。
优点:
1、观察者和被观察者是抽象耦合的。
2、建立一套触发机制。
缺点:
1、如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。
2、如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。
3、观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。
注意事项:
1、JAVA 中已经有了对观察者模式的支持类。
2、避免循环引用。
3、如果顺序执行,某一观察者错误会导致系统卡壳,一般采用异步方式。
实例:
1、创建 Subject 接口。
public interface Subject {
void add(Observer observer);// 添加观察者
void delete(Observer observer);// 删除观察者
void notifyObserver(String msg);// 通知观察者
}
2、创建Observer接口。
public interface Observer {
void update(String msg);
}
3、创建Subject实现类。
import java.util.ArrayList;
import java.util.List;
public class TestSubject implements Subject {// 被观察者的实现类
private List<Observer> list = new ArrayList<Observer>();// 用集合保存该被观察对象的观察者
@Override
public void add(Observer observer) {
list.add(observer);
}
@Override
public void delete(Observer observer) {
list.remove(observer);
}
@Override
public void notifyObserver(String msg) {
for (Observer o : list) {
o.update(msg);
}
}
}
4、创建Observer实现类。
public class TestObserver implements Observer {// 观察者的实现类
private String name;// 观察者的名称
public TestObserver() {
super();
// TODO 自动生成的构造函数存根
}
public TestObserver(String name) {
this.name = name;
}
@Override
public void update(String msg) {
System.out.println(this.name + ":[subject发表看法:" + msg + "]");
}
}
5、测试
public class Test {
public static void main(String[] args) {
Subject subject = new TestSubject();
TestObserver o1 = new TestObserver("张三");
TestObserver o2 = new TestObserver("李四");
TestObserver o3 = new TestObserver("王五");
subject.add(o1);
subject.add(o2);
subject.add(o3);
subject.notifyObserver("今天是个大晴天");
subject.delete(o2);
subject.notifyObserver("我更新了内容......,但不给李四看");
}
}
6、测试结果:
张三:[subject发表看法:今天是个大晴天]
李四:[subject发表看法:今天是个大晴天]
王五:[subject发表看法:今天是个大晴天]
张三:[subject发表看法:我更新了内容......,但不给李四看]
王五:[subject发表看法:我更新了内容......,但不给李四看]