教你写响应式框架(二)

还要做什么?

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

  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

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值