Java设计模式 ---- 观察者模式

一,观察者模式

    观察者模式又名发布-订阅模式,定义了对象之间的一对多依赖,多个对象同时监听一个对象,当被监听对象的状态发生改变时,它的所有依赖者都会收到通知并自动更新,被监听对象称为主题suject,监听对象称为观察者observer。项目中应用的MQ就是观察者模式的一种表现形式。

二,UML类图


* Subject : 主题类,提供注册,移除,通知观察者类的方法。

* ConcreteSubject : 具体主题类,对观察者进行管理并变更通知。

* Observer : 观察者的顶层类,提供update()方法接收被观察者类的通知。

* ConcreteObserver : 具体观察者类,用来接收被观察者类返回的状态进行业务处理。

三,JDK内置的观察者模式

    1,观察者类,实现Observer接口并重写update()方法;

public class JDKObserver implements Observer{

    private Observable observable;

    public JDKObserver(Observable observable) {
        this.observable = observable;
        observable.addObserver(this);
    }

    @Override
    public void update(Observable o, Object arg) {
        System.out.println("===观察者接收通知===");
    }
}

    2,被观察者类,继承Observable类

public class JDKObserable extends Observable {

    public void changed() {
        System.out.println("===发布者发布消息====");
        adviced();
    }

    public void adviced() {
        setChanged();
        notifyObservers();
    }
}

3,执行流程 --- JDK源码分析

    * 被观察者类状态变更完成后,首先必须调用父类的setChanged()方法,改变是否通知状态

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

    * changed状态改为true后,调用notifyObservers()方法,通知观察者类

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

    * 可以看到,被观察者类在通知观察者类之前,会将changed状态重新改为false

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

4,测试类

public class JDKObserverTest {
    public static void main(String[] args) {
        JDKObserable obserable = new JDKObserable();
        JDKObserver observer = new JDKObserver(obserable);
        obserable.changed();
    }
}

    * 首先创建一个被观察者类

    * 其次依次创建观察者类并传递被观察者类引用,依次绑定为该被观察者类的观察者类

    * 执行被观察者的更新方法后,观察者类同步变更


四,自定义观察者模式 --- 通过动态代理实现观察者模式

    1,事件VO

public class Event {

    // 事件源
    private Object source;

    // 通知目标
    private Object target;

    // 回调
    private Method method;

    public Event(Object source, Object target, Method method) {
        this.source = source;
        this.target = target;
        this.method = method;
    }

    public Object getSource() {
        return source;
    }

    public void setSource(Object source) {
        this.source = source;
    }

    public Object getTarget() {
        return target;
    }

    public void setTarget(Object target) {
        this.target = target;
    }

    public Method getMethod() {
        return method;
    }

    public void setMethod(Method method) {
        this.method = method;
    }

    @Override
    public String toString() {
        return "Event{" + "\r\n" +
                "source=" + source + "\r\n" +
                ", target=" + target + "\r\n" +
                ", method=" + method + '}';
    }
}

    2,事件枚举

public enum EventEnum {
    ON_ADD,
    ON_REMOVE,
    ON_EDIT,
    ON_QUERY;
}  

    3,事件绑定

public class EventListener {

    protected Map<Enum, Event> eventMap = new HashMap<Enum, Event>();

    public void addListener(Enum eventType, Object target, Method callBack) {
        // 注册事件
        eventMap.put(eventType, new Event(this, target, callBack));
    }

    protected void trigger(Enum eventType) {
        try {
            Event event = eventMap.get(eventType);
            if (null == event) {
                return;
            }
            event.getMethod().invoke(event.getTarget(), event);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}
    * Map的value可以用List进行替换,实现事件下的多观察者;

    4,被观察者类顶层接口

public interface SubjectInterface {
    public void add();

    public void remove();

}

    * 通过动态代理实现,确保强一致性;

    5,被观察者类

public class Subject extends EventListener implements SubjectInterface{

    public void add() {
        System.out.println("调用添加的方法");
        trigger(EventEnum.ON_ADD);
    }

    public void remove() {
        System.out.println("调用移除的方法");
        trigger(EventEnum.ON_REMOVE);
    }

}
    6,被观察者类代理对象及方法执行
public class JDKProxy {

    public static Object newInstance(final SubjectInterface observer) {
        SubjectInterface subjectInterface = (SubjectInterface) Proxy.newProxyInstance(observer.getClass().getClassLoader(),
                observer.getClass().getInterfaces(),
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        method.invoke(observer, args);
                        return null;
                    }
                });
        return subjectInterface ;
    }
}

    7,观察者类

public class Observer {

    public void advice(Event event) {
        System.out.println("========触发事件========" + "\r\n" + event);
    }
}

    8,客户端

public class ObserverTest {
    public static void main(String[] args) {
        try {
            // 观察者
            Observer observer = new Observer();

            // 发布者
            Subject subject = new Subject();
            subject.addListener(EventEnum.ON_ADD, observer, observer.getClass().getMethod("advice", new Class[]{Event.class}));
            SubjectInterface proxy = (SubjectInterface) JDKProxy.newInstance(subject);
            System.out.println(proxy.getClass());
            proxy.add();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

    * 该实现方式仿照JS的事件绑定Xxx("click", function(){});进行处理。

阅读更多
个人分类: Java设计模式
上一篇手写JDK动态代理
下一篇IDEA导入Spring源码环境搭建
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭