java基础-观察者模式

概述


观察者模式(0bserver Pattern),又叫发布-订阅
(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-监听器(Source/Listener)模式或从属者(Dependents)模式。定义一种一对多的依赖关系,一个主题对象可被多个观察者对象同时监听,使得每当主题对象状态变化时,所有依赖于它的对象都会得到通知并被自动更新。
属于行为型模式
 


生活场景

APP角标通知
起床闹钟设置


使用场景


1、当一个抽象模型包含两个方面内容,其中一个方面依赖于另一个方面;
2、其他一个或多个对象的变化依赖于另一个对象的变化;
3、实现类似广播机制的功能,无需知道具体收听者,只需忿发方播,系统中感兴趣的对象会自动接收该广播;
4、多层级嵌套使用,形成一种链式触发机制,、使得事件具备跨域(跨越两种观察者类型)通知。
 


优点


1、观察者和被观察者是松耦合(抽象耦合)的,符合依赖倒置原则;
2、分离了表示层(观察者)和数据逻辑层(被观察者),并且建立了一套触发机制,使得数据的变化可以响应到多个表示层上;
3、实现了一对多的通讯机制,支持事件注册机制,支持兴趣分发机制,当被观察者触发事件时,只有感兴趣的观察者可以接收到通知。
 


缺点


1、如果观察者数量过多,则事件通知会耗时较长;
2、事件通知呈线性关系,如果其中一个观察者处理事件卡壳,会影响后续的观察者接收该事件;
3、如果观察者和被观察者之间存在循环依赖,则可能造成两者之间的循环调用,导致系统崩溃;
 


代码栗子#老师关心学生#jdk实现

// 被观察者继承Observable 
public class Student extends Observable {

    private String name = "童鞋";

    private static final Student student = new Student();

    private Student() {
    }

    public static Student getInstance() {
        return student;

    }

    public String getName() {
        return name;
    }

    /**
     * 女神发小脾气,然后小强,大强去观察
     *
     * @param question
     */
    public void publishQuestion(Question question) {
        System.out.println(question.getUserName() + this.name + question.getContent());
        setChanged();
        notifyObservers(question);
    }

}
// 老师是观察者
public class Teacher implements Observer {

    private String name;

    public Teacher(String name) {
        this.name = name;
    }


    @Override
    public void update(Observable o, Object arg) {
        Student gper = (Student) o;
        Question question = (Question) arg;

        System.out.println("==================");
        System.out.println(name + ",你好! \n" +
                "您收到了一个来自" + gper.getName() + "的感冒信息,希望您处理。症状内容如下:\n" + question.getContent() +
                "\n" + "感冒人:" + question.getUserName());
    }
}

// 俺是被关系的东西
public class Question {


    private String userName;

    private String content;


    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }
}

jdk实现


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


    public void notifyObservers(Object arg) {
        /*
         *临时的观察者数组
         * 
         */
        Object[] arrLocal;

        synchronized (this) {
            
            // 判断是否更改
            if (!changed)
                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();
    }
}

// 观察者实现这个行为
public interface Observer {
    // 
    void update(Observable o, Object arg);
}

总结:jdk代理,一个类,一个接口,一个类是被观察者类,一个接口是观察者接口,

学生继承Observable,添加老师(实现行为观察者的Observer),

然后调用方法 setChanged();notifyObservers(question);就可以提醒所有的观察者了;

图1-1:

代码栗子#发布事件#guava


// 观察者
public class GuavaEvent {
    @Subscribe
    public void observer(String str) {
        System.out.println("执行observer方法,传参为:" + str);

    }
}

    public static void main(String[] args) {
        EventBus eventBus = new EventBus();

        GuavaEvent guavaEvent = new GuavaEvent();

        eventBus.register(guavaEvent);

        eventBus.post("xq");
     
    }

// 执行observer方法,传参为:xq

guava观察者代码解析

    
public class EventBus {
public void register(Object object) {
        this.subscribers.register(object);
    }

     private final SubscriberRegistry subscribers;


    private static final Logger logger = Logger.getLogger(EventBus.class.getName());
    private final String identifier;
    private final Executor executor;
    private final SubscriberExceptionHandler exceptionHandler;
    private final SubscriberRegistry subscribers;
    private final Dispatcher dispatcher;


    EventBus(String identifier, Executor executor, Dispatcher dispatcher, SubscriberExceptionHandler exceptionHandler) {
        this.subscribers = new SubscriberRegistry(this);
        this.identifier = (String)Preconditions.checkNotNull(identifier);
        this.executor = (Executor)Preconditions.checkNotNull(executor);
        this.dispatcher = (Dispatcher)Preconditions.checkNotNull(dispatcher);
        this.exceptionHandler = (SubscriberExceptionHandler)Preconditions.checkNotNull(exceptionHandler);
    }

}

// 以后补吧

1

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值