观察者模式

观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。 这个主题对象在状态上发生变化时,会通知所有观察者对象,让它们能够自动更新自己。
让主题和观察者之间松耦合

UML图为:

这里写图片描述

Subject类

public class Subject {
    private List<Observer> list = new ArrayList<>();
    private String 

    public String getData() {
        return data;
    }

    //添加观察者
    public void attach(Observer observer){
        list.add(observer);
    }

    //删除观察者
    public void detach(Observer observer){
        list.remove(observer);
    }

    //通知
    public void notifyObservers(String data){
        this.data = data;
        for (Observer observer : list) {
            observer.update(data);
        }
    }
}

Observer接口:

public interface Observer {
    void update(String data);
}

具体实现类:

public class Teacher extends Subject{
    public void sendHomework(String data){
        notifyObservers(data);
    }
}
public class Student implements Observer{

    private int num;

    public Student(int num) {
        this.num = num;
    }

    @Override
    public void update(String data) {
        System.out.println("Student" + num + " get homework:" + data);
    }

}

测试类:

public class Test {
    public static void main(String[] args) {
        Teacher teacher = new Teacher();
        for (int i = 0; i < 5; i++) {
            Student student = new Student(i);
            teacher.attach(student);
        }
        teacher.notifyObservers("coding");
    }
}

输出:

Student0 get homework:coding
Student1 get homework:coding
Student2 get homework:coding
Student3 get homework:coding
Student4 get homework:coding

二、java内置的观察者模式
在java.util库里,提供了一个Observable类以及一个Observer接口,对观察者模式进行支持

举个例子,老师给学生们发布作业

class Teacher extends Observable{

    private String data;

    public String getData() {
        return data;
    }

    public void sendHomework(String data){
        this.data = data;
        setChanged();//状态发生改变
        notifyObservers(data);
    }
}

class Student implements Observer{

    private int num;

    public Student(int num) {
        this.num = num;
    }

    @Override
    public void update(Observable o, Object arg) {
        System.out.println("Student" + num + " get homework:" + arg);
    }

}

这是观察者模式中的推模式

推模型和拉模型
推模型
主题对象向观察者推送主题的详细信息,不管观察者是否需要,推送的信息通常是主题对象的全部或部分数据。

拉模型
主题对象在通知观察者的时候,只传递少量信息。如果观察者需要更具体的信息,由观察者主动到主题对象中获取,相当于是观察者从主题对象中拉数据。一般这种模型的实现中,会把主题对象自身通过update()方法传递给观察者,这样在观察者需要获取数据的时候,就可以通过这个引用来获取了。

下面是拉模式:

class Teacher extends Observable{

    private String data;

    public String getData() {
        return data;
    }

    public void sendHomework(String data){
        this.data = data;
        setChanged();
        notifyObservers();//通知
    }
}

class Student implements Observer{

    private int num;

    public Student(int num) {
        this.num = num;
    }

    @Override
    public void update(Observable o, Object arg) {
        System.out.println("Student" + num + " get homework:" + ((Teacher)o).getData());//拉出数据
    }

}

Observable类

package java.util;

public class Observable {
    private boolean changed = false;//设置是否有发生改变
    private Vector<Observer> obs;//ector相比于ArrayList来说,它是线程安全的,
    //如果在迭代的时候删除了某个监听者就会造成错误

    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);
    }

    public void notifyObservers(Object arg) {
    //通知
        Object[] arrLocal;

        synchronized (this) {
            if (!changed)//如果没有改变就返回,不通知
                return;
            arrLocal = obs.toArray();//将Vector转换成数组
            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();
    }
}

Observer接口

public interface Observer {
    void update(Observable o, Object arg);//更新
}

java.util.Observerable有一些问题,首先它是一个类,所以必须设计一个类来继承它,但是如果某类同时具有Observable类和另一个超类的行为,就不行了,因为java不支持多重继承,没有Observable接口,所以无法建立自己的实现。

Observable将关键的方法保护起来,setChange()方法被保护(定义为protected),只有继承Observable才能创建Observable实例并组合到自己的对象中,违反了设计原则“多用组合,少用继承”

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值