设计模式之【观察者模式】

观察者模式动机与定义

模式动机

一个对象的状态改变会引起其他对象的状态改变。

模式定义

观察者模式(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: "居安思危"

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值