为什么要这么做?
在教你写响应式框架(三)中,我们还留有一个问题没有说明:为什么OperatorMap中的泛型和Operator中泛型参数的位置正好是相反的?
Operator本身是对Observable发射的数据进行转换的,因此往往出现operator转换之后返回的数据类型发生变化,这时候将泛型参数颠倒一下,就可以保证call方法返回的Observer能够订阅Observable发射出的数据。举个例子来说明:
Observable<Integer> observable = Observable.create(new Observable.OnAttach<String>() {
@Override
public void call(Observer<? super String> observer) {
observer.update("1");
}
}).map(new IFun<String, Integer>() {
@Override
public Integer call(String s) {
return Integer.valueOf(s);
}
});
observable.attach(new Observer<Integer>() {
@Override
public void update(Integer aFloat) {
System.out.println(aFloat);
}
});
在上面的代码中,map操作符的操作参数为IFun<String,Integer>
,而为了使map操作产生的Observer能够订阅create()方法产生的Observable,这时的OperatorMap中的call方法需要产生Observer<String>
类型的对象,这使你会发现简单的泛型参数对掉就可以轻松的解决了这个问题。这是来看一下OperatorMap中的call方法:
public Observer<? super T> call(Observer<? super R> observer) {
return new Observer<T>() {
@Override
public void update(T t) {
observer.update(convert.call(t));
}
};
}
到现在为止,我们已经解决的一些问题,接下来,我们就来看看如何扩展这个小框架。
扩展,增强现有功能
现在我想要为框架增添过滤操作,该怎么做呢?考虑该操作会只过滤掉不满足条件的元素,而不会改变元素类型,因此我们如下设计该类:
public class OperatorFilter<T> implements Observable.Operator<T, T> {
private IFun<? super T, Boolean> fun;
public OperatorFilter(IFun<? super T, Boolean> fun) {
this.fun = fun;
}
@Override
public Observer<? super T> call(Observer<? super T> observer) {
return new Observer<T>() {
@Override
public void update(T t) {
if (fun.call(t).booleanValue()) {
observer.update(t);
}
}
};
}
}
随后,我们在Observable添加函数:
public <R> Observable<R> filter(IFun<? super T, Boolean> fun) {
return lift(new OperatorFilter(fun));
}
准备工作已经完成,让我们测试一下:
public class Client {
public static void main(String[] args) {
Observable.create(new Observable.OnAttach<Integer>() {
@Override
public void call(Observer<? super Integer> observer) {
for (int i = 0; i < 10; i++) {
observer.update(new Random().nextInt(10));
}
}
}).filter(integer -> integer > 5)
.map(integer -> "num:" + integer)
.attach(integer -> System.out.println(integer));
}
}
运行结果为:
num:8
num:6
num:6
num:9
到现在为止,我们构建出了框架的基本主干,并支持了map和filter操作,尽管它看起来有点low,但本教程的目的更倾向于传递一种响应式编程的理念,让每个人都能理解,拉低响应式框架开发的门槛。
好吧,最后给它起了个牛逼的名字叫做”ErJava”,就是easy Reactive Java的意思。
总结
这四个章节一步一步教你如何设计和改进既有的结构,你发现整个框架从最基础的观察者模式出发,在我们不断的提问中得到演进。这与其他框架的开发流程并没有太大的区别,实际上大部分框架的开发工作在之前都会做一个雏形的设计,随着后面的发展才慢慢得到改善,这正如我们所做的一样。
除此之外,你会发现我们尽可能的遵从OOD的设计理念,当然,一些经验性的设计方法也起了很大的作用。