观察者模式动机与定义
模式动机
一个对象的状态改变会引起其他对象的状态改变。
模式定义
观察者模式(Observer Pattern)定义:定义对象间一种一对多的依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。
观察者模式结构与分析
模式结构
观察者模式包含如下4个角色:
- Subject(目标)
- ConcreteSubject(具体目标)
- Observer(观察者)
- ConcreteObserver(具体观察者)
模式分析
通用代码:
抽象观察目标 Subject 类
/**
* 抽象 观察目标 类
*/
public abstract class Subject {
protected ArrayList observers = new ArrayList(); // 观察者集合
// 依赖关系:某个类的方法使用另一个类的对象作为参数,这里使用 Observer 类的对象作为参数
public abstract void attach(Observer observer); // 用于增加一个观察者对象
public abstract void detach(Observer observer); // 用于删除一个观察者对象
public abstract void notifyObserver(); // 用于通知各个观察者对象并调用它们的 update() 方法
}
具体观察目标 ConcreteSubject 类
/**
* 具体 观察目标 类
*/
public class ConcreteSubject extends Subject {
@Override
public void attach(Observer observer) {
observers.add(observer); // 增加一个观察者
}
@Override
public void detach(Observer observer) {
observers.remove(observer); // 删除一个观察者
}
@Override
public void notifyObserver() {
for (Object obs : observers) { // 或者可以直接写成 (Observer obs : observers)
((Observer) obs).update(); // obs 需要强制类型转换为 Observer 才会有 update() 方法
}
}
}
抽象观察者 Observer 接口
/**
* 抽象 观察者 接口
*/
public interface Observer {
public void update(); // 观察目标状态发生改变时,观察者通过该方法做出相应的改变
}
具体观察者 ConcreteObserver 类
/**
* 具体 观察者 类
*/
public class ConcreteObserver implements Observer {
@Override
public void update() {
// 具体更新代码
System.out.println("观察目标发生改变,调用 notifyObserver() 方法,通知观察者调用 update() 方法,做相应的改变");
}
}
客户端代码 Client 类
/**
* 主函数 测试
*/
public class Client {
public static void main(String[] args) {
Subject subject = new ConcreteSubject(); // 生成具体的 观察目标 对象
Observer observer = new ConcreteObserver(); // 生成具体的 观察者 对象
subject.attach(observer); // 增加监听 观察目标 的 观察者
subject.notifyObserver(); // 观察目标 发生改变
}
}
观察者模式实例
观察者模式实例之猫、狗与老鼠
实例说明
假设猫是老鼠和狗的观察目标,老鼠和狗是观察者,猫叫老鼠跑,狗也跟着叫,下面使用观察者模式描述该过程。
实例代码
1) 抽象目标类 MySubject
/**
* 抽象目标类 MySubject
*/
public abstract class MySubject {
/**
* 程序中使用 ArrayList 和 Vector 的主要区别是:
* 1) ArrayList 是线程异步的,不安全
* 2) Vector 是线程同步的, 安全
*/
protected ArrayList<MyObserver> observers = new ArrayList<>(); // 用于存储观察者对象
// protected Vector<MyObserver> observers = new Vector<>();
// 针对抽象层编程
public void attach(MyObserver observer) { // 注册方法
observers.add(observer);
}
// 针对抽象层编程
public void detach(MyObserver observer) { // 注销方法
observers.remove(observer);
}
public abstract void cry(); // 抽象通知方法
}
*需要主要的是 attach() 方法和 detach() 方法都必须针对抽象观察目标进行编程,任何抽象观察目标的子类对象都可以注册或注销。
2) 抽象观察者类 MyObserver
/**
* 抽象观察者接口 MyObserver
*/
public interface MyObserver {
public void response(); // 抽象响应方法
}
3) 具体目标类 Cat (猫类)
/**
* 具体观察者类 Cat (猫类)
*/
public class Cat extends MySubject {
@Override
public void cry() {
System.out.println("猫发出叫声!");
System.out.println("---------------------------------------------");
// 遍历,通知所用监听它的观察者
for (Object obs : observers) {
((MyObserver) obs).response(); // 这里用了强制类型转化,也可以直接使用下面的另一种方法
}
// for (MyObserver obs : observers) {
// obs.response();
// }
}
}
4) 具体观察者类 Mouse (老鼠类)
/**
* 具体观察者类 Mouse (老鼠类)
*/
public class Mouse implements MyObserver {
@Override
public void response() {
System.out.println("老鼠听到了猫叫声,老鼠努力逃跑!");
}
}
5) 具体观察者类 Dog (狗类)
/**
* 具体观察者类 Dog (狗类)
*/
public class Dog implements MyObserver {
@Override
public void response() {
System.out.println("狗听到了猫叫声,狗也跟着叫!");
}
}
6)客户端测试类 Client
/**
* 客户端测试类 Client
*/
public class Client {
public static void main(String[] args) {
MySubject subject = new Cat();
MyObserver obs1, obs2, obs3;
obs1 = new Mouse(); // 创建观察者
obs2 = new Mouse();
obs3 = new Dog();
subject.attach(obs1); // 添加监听观察目标的观察者对象
subject.attach(obs2);
subject.attach(obs3);
subject.cry();
}
}
7)输出结果
PS: "居安思危"