个人博客:打开链接
一、定义
观察者模式属于对象的行为模式,观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题(被观察者)对象。这个主题对象在状态上发生变化时,会通知所有观察者对象,使它们能够自动更新自己。
二、类图
三、观察者模式的结构
被观察者:从类图中可以看到,类中有一个用来存放观察者对象的Vector容器(之所以使用Vector而不使用List,是因为多线程操作时,Vector在是安全的,而List则是不安全的),这个Vector容器是被观察者类的核心,另外还有三个方法:attach方法是向这个容器中添加观察者对象;detach方法是从容器中移除观察者对象;notify方法是依次调用观察者对象的对应方法。这个角色可以是接口,也可以是抽象类或者具体的类,因为很多情况下会与其他的模式混用,所以使用抽象类的情况比较多。
观察者:观察者角色一般是一个接口,它只有一个update方法,在被观察者状态发生变化时,这个方法就会被触发调用。
具体的被观察者:使用这个角色是为了便于扩展,可以在此角色中定义具体的业务逻辑。
具体的观察者:观察者接口的具体实现,在这个角色中,将定义被观察者对象状态发生变化时所要处理的逻辑。
四、使用场景
一个对象的状态发生改变, 通知到某些与它相关的对象,让他们可以随之做出相应的变化
1、抽象主题类
//抽象主题类
public abstract class Subject {
// 观察者集合
private List<Observer> list = new ArrayList<Observer>();
// 添加观察者
public void register(Observer observer) {
list.add(observer);
}
//删除
public void remove(Observer observer) {
if (list.contains(observer)) {
list.remove(observer);
}
}
public void change(String status) {
this.notifyObserver(status);
}
//通知所有观察者
private void notifyObserver(String status) {
for (Observer observer : list) {
observer.update(status);
}
}
}
2、主题具体实现类
//具体主题角色类
public class RealSubject extends Subject {
private String status;
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public void change(String status) {
System.out.println("当前主题状态:" + status);
super.change(status);
}
}
3、观察者接口
//观察者接口
public interface Observer {
public void update(String status);
}
4、具体观察者接口实现
//具体观察者类
public class RealObserver implements Observer {
private String name;
private String innerStatus;
public RealObserver(String name) {
super();
this.name = name;
}
@Override
public void update(String status) {
this.innerStatus = status;
System.out.println("观察者" + name + ",状态:" + innerStatus);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
5、客户端Client测试
public class Client {
public static void main(String[] args) {
// 创建主题
RealSubject subject = new RealSubject();
// 创建观察者
Observer observerA = new RealObserver("张三");
Observer observerB = new RealObserver("李四");
// 给主题添加观察者
subject.register(observerA);
subject.register(observerB);
// 改变主题内容状态
subject.change("start");
}
}
五、优点
易扩展: 观察者与被观察者之间是属于轻度的关联关系,并且是抽象耦合的,这样,对于两者来说都比较容易进行扩展。
六、缺点
性能欠佳:如一个主题被大量观察者注册,则通知所有观察者会花费较高代价
容易阻塞: 如果某些观察者的响应方法被阻塞,整个通知过程即被阻塞,其它观察者不能及时被通知