2、观察者模式

原文链接

1、概述

  • 观察者模式定义了对象之间的一对多依赖关系,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并且自动更新。
  • 在这里,发生改变的对象称之为观察目标,而被通知的对象称之为观察者。一个观察目标可以对应多个观察者,而且这些观察者之间没有相互联系,所以么可以根据需要增加和删除观察者,使得系统更易于扩展。所以观察者提供了一种对象设计,让主题和观察者之间以松耦合的方式结合。

在这里插入图片描述

  • 观察者模式包含如下角色:
    • Subject: 目标
    • ConcreteSubject: 具体目标
    • Observer: 观察者
    • ConcreteObserver: 具体观察者

2、代码例子

  • 实现一个植物(目标)开花后会通知昆虫(观察者)来采蜜,关闭后昆虫回家的例子
  • Observer
package com.company;

public interface Insect {
    void work();
    void home();
}
  • ConcreteObserver
package com.company;

public class Bee implements Insect {

    private int id;

    public Bee(int id) {
        this.id = id;
    }

    @Override
    public void work() {
        System.out.println("蜜蜂" + id + "工作");
    }

    @Override
    public void home() {
        System.out.println("蜜蜂" + id + "回家");
    }
}
  • Subject
package com.company;

public interface Plant {
    void registerInsect(Insect insect);
    void unregisterInsect(Insect insect);
    void notifyInsect(boolean isOpen);
}
  • ConcreteSubject
package com.company;

import java.util.ArrayList;
import java.util.List;

public class Flower implements Plant {

    private List<Insect> insects = new ArrayList<>();

    @Override
    public void registerInsect(Insect insect) {
        insects.add(insect);
    }

    @Override
    public void unregisterInsect(Insect insect) {
        insects.remove(insect);
    }

    @Override
    public void notifyInsect(boolean isOpen) {
        for (int i = 0; i < insects.size(); i++) {
            if (isOpen){
                insects.get(i).work();
            } else {
                insects.get(i).home();
            }
        }
    }
}
  • 测试
package com.company;

public class Main {

    public static void main(String[] args) {

        // 一个Subject
        Plant flower = new Flower();

        // 多个Observe
        Insect insect1 = new Bee(1);
        Insect insect2 = new Bee(2);
        Insect insect3 = new Bee(3);

        flower.registerInsect(insect1);
        flower.registerInsect(insect2);
        flower.registerInsect(insect3);

        flower.notifyInsect(true);
        flower.notifyInsect(false);

        flower.unregisterInsect(insect1);
        flower.unregisterInsect(insect2);
        flower.unregisterInsect(insect3);
    }
}
  • 主要思路:Subject提供注册(添加Observer)、注销(移除Observer)、通知(当Subject发生某种变化后,调用notify方法,通知所有的Observer对象)
  • RxJava的是拓展的观察者模式,A对象的行为影响B对象,B对象影响C对象,可以使用观察者模式创建一种链式触发机制。

3、Android自带的观察者

3-1、观察者Observer源码

  • 位于java.util目录下
public interface Observer {
    void update(Observable o, Object arg);
}

3-2、被观察者Observable源码

  • 位于java.util目录下
public class Observable {
  
    /**
     * 被观察者的数据是否改变
     */  
    private boolean changed = false;

    /**
     * 保存观察者的集合
     */  
    private Vector<Observer> obs;

    public Observable() {
        obs = new Vector<>();
    }

    /**
     * 添加观察者
     */  
    public synchronized void addObserver(Observer o) {
        if (o == null)
            throw new NullPointerException();
        if (!obs.contains(o)) {
            obs.addElement(o);
        }
    }

    /**
     * 删除观察者
     */  
    public synchronized void deleteObserver(Observer o) {
        obs.removeElement(o);
    }


    public void notifyObservers() {
        notifyObservers(null);
    }

    /**
     * 通知观察者,hasChanged为true才真真通知观察者
     */  
    public void notifyObservers(Object arg) {

        Object[] arrLocal;

        synchronized (this) {
            if (!hasChanged())
                return;
            arrLocal = obs.toArray();
            clearChanged();
        }

        for (int i = arrLocal.length-1; i>=0; i--)
            ((Observer)arrLocal[i]).update(this, arg);
    }

    public synchronized void deleteObservers() {
        obs.removeAllElements();
    }

    protected synchronized void setChanged() {
        changed = true;
    }

    protected synchronized void clearChanged() {
        changed = false;
    }


    public synchronized boolean hasChanged() {
        return changed;
    }

    /**
     * 观察者数量
     */
    public synchronized int countObservers() {
        return obs.size();
    }
}

4、观察者模式的推\拉模型

  • 推拉模型本质区别只是在于update传入的参数是一个属性还是对象本身
  • 推模型是假定被观察者知道观察者需要的数据
  • 拉模型是被观察者 不知道观察者具体需要什么数据,没有办法的情况下,干脆把自身传递给观察者,让观察者自己去按需要取值
  • 优缺点
    • 推模型可能会使得观察者对象难以复用,因为观察者的update()方法是按需要定义的参数,可能无法兼顾没有考虑到的使用情况。这就意味着出现新情况的时候,就可能提供新的update()方法,或者是干脆重新实现观察者;
    • 而拉模型就不会造成这样的情况,因为拉模型下,update()方法的参数是主题对象本身,这基本上是主题对象能传递的最大数据集合了,基本上可以适应各种情况的需要

4-1、推模型

  • Observer:观察者
package com.xinhe.testandroid.observe;

import java.util.Observable;
import java.util.Observer;

public class Bee implements Observer {

    private static final String TAG = "Bee";

    private int id;

    public Bee(int id) {
        this.id = id;
    }

    @Override
    public void update(Observable o, Object arg) {
        if ((Boolean)arg){
            System.out.println("update: true"+id);
        } else {
            System.out.println("update: false"+id);
        }
    }
}
  • Observable:被观察者
public class Flower extends Observable {

    public void notifyInsect(boolean isOpen){

        // 通知改变
        this.setChanged();
        // 通知所有观察者
        this.notifyObservers(isOpen);
    }
}
  • 验证
        // 一个Subject
        Flower flower = new Flower();

        // 多个Observe
        Bee insect1 = new Bee(1);
        Bee insect2 = new Bee(2);
        Bee insect3 = new Bee(3);

        flower.addObserver(insect1);
        flower.addObserver(insect2);
        flower.addObserver(insect3);

        flower.notifyInsect(true);
        flower.notifyInsect(false);

        flower.deleteObserver(insect1);
        flower.deleteObserver(insect2);
        flower.deleteObserver(insect3);

4-2、拉模型

  • 再写个拉模型例子
package com.xinhe.testandroid.observe;

import java.util.Observable;

public class Flower extends Observable {

    private boolean isOpen;

    public boolean getOpen(){
        return isOpen;
    }

    public void notifyInsect(boolean isOpen){

        this.isOpen = isOpen;

        // 通知改变
        this.setChanged();
        // 通知所有观察者
        this.notifyObservers(this);
    }
}
  • Bee
package com.xinhe.testandroid.observe;

import java.util.Observable;
import java.util.Observer;

public class Bee implements Observer {

    private static final String TAG = "Bee";

    private int id;

    public Bee(int id) {
        this.id = id;
    }

    @Override
    public void update(Observable o, Object arg) {

        Flower flower = (Flower) arg;

        if (flower.getOpen()){
            System.out.println("update: true"+id);
        } else {
            System.out.println("update: false"+id);
        }
    }
}
  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值