行为型模式(七):观察者模式

1、模式的定义与特点

观察者(Observer)模式:指多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
这种模式又称作发布-订阅模式、模型-视图模式,它是对象行为型模式。

观察者模式是一种对象行为型模式,其优点如下:
1、降低了目标与观察者之间的耦合关系,两者之间是抽象耦合关系。
2、目标与观察者之间建立了一套触发机制。

缺点:
1、目标与观察者之间的依赖关系并没有完全解除,而且有可能出现循环引用。
2、当观察者对象很多时,通知的发布会花费很多时间,影响程序的效率。

2、模式的结构

实现观察者模式时要注意具体目标对象和具体观察者对象之间不能直接调用,否则将使两者之间紧密耦合起来,这违反了面向对象的设计原则。

观察者模式的主要角色:
1、抽象主题(Subject)角色:也叫抽象目标类,它提供了一个用于保存观察者对象的聚集类和增加、删除观察者对象的方法,以及通知所有观察者的抽象方法。
2、具体主题(Concrete Subject)角色:也叫具体目标类,它实现抽象目标中的通知方法,当具体主题的内部状态发生改变时,通知所有注册过的观察者对象。
3、抽象观察者(Observer)角色:它是一个抽象类或接口,它包含了一个更新自己的抽象方法,当接到具体主题的更改通知时被调用。
4、具体观察者(Concrete Observer)角色:实现抽象观察者中定义的抽象方法,以便在得到目标的更改通知时更新自身的状态。
在这里插入图片描述

图1 观察者模式的结构图

3、模式的应用场景

1、对象间存在一对多关系,一个对象的状态发生改变会影响其他对象。
2、当一个抽象模型有两个方面,其中一个方面依赖于另一方面时,可将这二者封装在独立的对象中以使它们可以各自独立地改变和复用。

4、模式的扩展

在Java中,通过java.util.Observable类和java.util.Observer接口定义了观察者模式,只要实现它们的子类就可以编写观察者模式实例。

1、Observable类
Observable类是抽象目标类,它有一个Vector向量,用于保存所有要通知的观察者对象。它有3 个重要方法:
(1)void addObserver(Observer o)方法:用于将新的观察者对象添加到向量中。
(2)void notifyObservers(Object arg)方法:调用向量中的所有观察者对象的update()方法,通知它们数据发生改变。通常越晚加入向量的观察者越先得到通知。
(3)void setChange()方法:用来设置一个boolean类型的内部标志位,注明目标对象发生了变化。当它为真时,notifyObservers()才会通知观察者。

2、Observer接口
Observer接口是抽象观察者,它监视目标对象的变化,当目标对象发生变化时,观察者得到通知,并调用void update(Observable o,Object arg)方法,进行相应的工作。

5、模式的实现

在这里插入图片描述

图2 示例结构

抽象观察者角色:

package com.example.designpattern.observer;

/**
 * 抽象观察者角色
 *
 * @author Administrator
 * @date 2020/8/6
 */
interface IObserver {
    public void update(String state);
}

抽象主题角色:

package com.example.designpattern.observer;

import java.util.ArrayList;

/**
 * 抽象主题角色
 *
 * @author Administrator
 * @date 2020/8/6
 */
abstract class AbstractTheme {
    private ArrayList<IObserver> list = new ArrayList<>();

    public void attach(IObserver o) {
        list.add(o);
    }

    public void detach(IObserver o) {
        list.remove(o);
    }

    public void notifyObservers(String state) {
        for (IObserver observer : list) {
            observer.update(state);
        }
    }
}

具体主题角色:

package com.example.designpattern.observer;


/**
 * 具体主题角色
 *
 * @author Administrator
 * @date 2020/8/6
 */
class ConcreteTheme extends AbstractTheme {
    private String state;

    public ConcreteTheme(String state) {
        this.state = state;
    }

    public String getState() {
        return state;
    }

    public void setState(String state) {
        this.state = state;
    }

    public void change(String newState) {
        this.state = newState;
        //通知所有注册在该主题的观察者进行状态更新
        this.notifyObservers(newState);
    }
}

具体观察者角色:

package com.example.designpattern.observer;

/**
 * 具体观察者角色
 *
 * @author Administrator
 * @date 2020/8/6
 */
class ConcreteObserver implements IObserver {
    private String pageState;
    private String pageLevel;

    public ConcreteObserver(String pageLevel) {
        this.pageLevel = pageLevel;
    }

    public String getPageState() {
        return pageState;
    }

    public void setPageState(String pageState) {
        this.pageState = pageState;
    }

    public String getPageLevel() {
        return pageLevel;
    }

    public void setPageLevel(String pageLevel) {
        this.pageLevel = pageLevel;
    }

    @Override
    public void update(String state) {
        pageState = state;
    }
}

调用:

package com.example.designpattern.observer;

/**
 * @author Administrator
 * @date 2020/8/6
 */
class Client {
    public static void main(String[] args) {
        // 1、创建一个具体主题
        ConcreteTheme theme = new ConcreteTheme("红色主题状态");

        // 2、创建网站页面  属于观察者角色
        ConcreteObserver p1 = new ConcreteObserver("一级页面");
        ConcreteObserver p2 = new ConcreteObserver("二级页面");
        ConcreteObserver p3 = new ConcreteObserver("三级页面");

        // 3、注册观察者
        theme.attach(p1);
        theme.attach(p2);
        theme.attach(p3);

        theme.change("绿色状态");

        // 主题变为绿色状态后,页面状态随之改变
        System.out.println(p1.getPageLevel() + "的状态为:" + p1.getPageState());
        System.out.println(p2.getPageLevel() + "的状态为:" + p2.getPageState());
        System.out.println(p3.getPageLevel() + "的状态为:" + p3.getPageState());
    }
}

测试结果:
在这里插入图片描述

图3 测试结果

6、PPT素材

在这里插入图片描述

01

在这里插入图片描述

02

在这里插入图片描述

03

在这里插入图片描述

04

在这里插入图片描述

05

在这里插入图片描述

06

在这里插入图片描述

07

在这里插入图片描述

08

在这里插入图片描述

09

在这里插入图片描述

10

在这里插入图片描述

11

在这里插入图片描述

12

在这里插入图片描述

13

在这里插入图片描述

14

在这里插入图片描述

15

微信公众号: TechU
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值