教你写响应式框架(二)

来源:互联网 发布:红外预警卫星 算法 编辑:程序博客网 时间:2024/06/18 09:39

还要做什么?

在教你写响应式框架(一)中我们介绍了观察者模式,现在我们将基于上一篇中的代码进行改造。当然,我们是有目的的改造:

  1. 在响应式框架中,观察者是可能随时产生,种类多,生命周期却短暂.
  2. 我们希望操作是异步的,并且只有在观察者被注册到被观察者上时,被观察者才生效.

在开始改造之前,为了避免没看过上一篇的童鞋产生断裂感,我仍然先贴一下观察者的实现,为了从能够”望文生义”,其中有一些小细节我做了调整:

//被观察者public abstract class Observable {    private List<Observer> list = new ArrayList<>();    public void attach(Observer observer) {        list.add(observer);    }    public void detach(Observer observer) {        list.remove(observer);    }    public void notifyObservers(String newState) {        list.stream().forEach(ob->{ob.update(newState);});    }}//被观察者的具体实现public class ConcreteObservable extends Observable {    public void change(String state) {        this.notifyObservers(state);    }}//观察者接口public interface Observer {    void update(String state);}//观察者的具体实现public class ConcreteObserver implements Observer {    @Override    public void update(String state) {        System.out.println("主题状态改变了:" + state);    }}//客户端测试代码public class Client {    public static void main(String[] args) {        ConcreteObservable subject = new ConcreteObservable();        subject.attach(new Observer() {            @Override            public void update(String state) {                System.out.println("主题状态变化:" + state);            }        });        subject.change("2");    }}

别样的观察者模式

针对上面提到的第一个需求,我们很容易理解,只提供给用户相关的接口就行,具体实现由用户根据实际情况来实现.

那如何实现第二个需求呢?暂时我们先不说,直接从代码中看实现:

//被观察者public class Observable {    protected OnAttach onAttach;    private Observable() {    }    public Observable(OnAttach onAttach) {        this.onAttach = onAttach;    }    public void attach(Observer observer) {        onAttach.call(observer);    }    public interface OnAttach {        void call(Observer observer);    }}//观察者public interface Observer {    void update(String state);}//客户端代码public class Client {    public static void main(String[] args) {        Observable observable = new Observable(new Observable.OnAttach() {            @Override            public void call(Observer observer) {                observer.update("1");            }        });        observable.attach(new Observer() {            @Override            public void update(String state) {                System.out.println("state:" + state);            }        });    }}

经过一番折磨之后,对原有的代码进行了重构,重点关注Observable类.在Observable中,我们定义OnAttach接口,该接口负责通知观察者.同时attach方法在将观察者注册到被观察者上之后,会调用OnAttach的call方法来实现自动通知,这样做的好处就是我们不需要再手动调用call方法来通知被观察者了—-对用户屏蔽细节.

为了更方便理解,我们将客户端的代码写成你所熟悉的方式:

public class Client {    public static void main(String[] args) {        //注册关系,简化了手动通知观察者的过程        Observable.OnAttach onAttach = new Observable.OnAttach() {            @Override            public void call(Observer observer) {                observer.update("1");            }        };        //被观察者        Observable observable = new Observable(onAttach);        //观察者        Observer observer = new Observer() {            @Override            public void update(String state) {                System.out.println("state:" + state);            }        };        //将观察者注册到被观察者上        observable.attach(observer);    }}

我们发现最大的变化就是被观察者,尤其是通过OnAttach接口来实现自动通知,现在我们分析一下:
首先,我们实现OnAttach接口,该接口含有唯一的方法call.call方法接受一个Observer对象,此对象就是我们的观察者对象observer.当执行observable.attach(observer)方法时,会引起call方法的调用,进而执行observer.update(“1”),然后执行System.out.println(“state:” + state);,不难发现这就是标准观察者模式的变种.


重构,改善原有设计

分析完之后,我们再看一下代码,哇,好low,这么低级的代码看起来像坨大便一样.既然要作为一个框架,必然要尽可能的通用和易于理解.因此我们在上面代码的基础上修改两点:

  • 引入泛型
  • 用静态工厂方法代替构造器.

引入泛型想必每个人都能理解,但是用静态工厂可能有些人觉得多此一举了,对此请各位自行查阅Joshua Bloch大神的<>的第一节吧.

重构后的代码:

//被观察者public class Observable<T> {    protected OnAttach onAttach;    public Observable(OnAttach onAttach) {        this.onAttach = onAttach;    }    public static <T> Observable<T> create(OnAttach<T> onAttach) {        return new Observable(onAttach);    }    public void attach(Observer<T> observer) {        onAttach.call(observer);    }    public interface OnAttach<T> {        void call(Observer<? super T> observer);    }}//观察者public interface Observer<T> {    void update(T state);}//客户端代码public class Client {    public static void main(String[] args) {        //注册关系,简化了手动通知观察者的过程        Observable.OnAttach onAttach = new Observable.OnAttach() {            @Override            public void call(Observer observer) {                ArrayList<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));                observer.update(list);            }        };        //被观察者        Observable observable = Observable.create(onAttach);        //观察者        Observer observer = new Observer<ArrayList<Integer>>() {            @Override            public void update(ArrayList<Integer> state) {                state.stream().forEach(p -> {                    System.out.println(p);                });            }        };        //将观察者注册到被观察者上        observable.attach(observer);    }}

现在的代码看起来是不是好一点了?到现在,你可能会说:压根没什么用嘛.对的,起码到目前来说,并没有什么用.在下一节中,我们将引入操作符,这才是我们关注的重点.

完整项目可见EasyReactive

3 0
原创粉丝点击