Java I/O通用api设计 (二)

来源:互联网 发布:淘宝 百科 编辑:程序博客网 时间:2024/06/07 12:03

上一篇处理了基本的I/O传输,我们常常还要做些其它的事。可能要计数一下传输了多少个数据,过滤一下数据,或者是每1000条数据做一下日志,又或者要看一下正在进行什么操作。既然输入输出已经分离,这些事变成在输入输出的协调代码中简单地插入一些逻辑。大部分协调代码有类似的功能,可以放到标准的工具方法中,更方便使用。

第一个标准修饰器是一个过滤器。实现时我用到了Specification。

public interface Specification<T> {    boolean test(T item);}

从上一篇可以看到最后的操作是

Inputs.text(source).transferTo(Outputs.text(destination));
要做其他事情只能对Output进行增强。因为sender和receiver都是通过他来调用的,同样的需要对这两个进行增强。
public class Filters {    static class SpecificationOutputWrapper<T, ReceiverThrowableType extends Throwable>            implements Output<T, ReceiverThrowableType> {        final Output<T, ReceiverThrowableType> output;        final Specification<T> specification;        public SpecificationOutputWrapper(Output<T, ReceiverThrowableType> output, Specification<T> specification) {            this.output = output;            this.specification = specification;        }        public <SenderThrowableType extends Throwable> void receiveFrom(Sender<T, SenderThrowableType> sender)                throws ReceiverThrowableType, SenderThrowableType {            output.receiveFrom(new SpecificationSenderWrapper<T, SenderThrowableType>(sender, specification));        }    }    static class SpecificationSenderWrapper<T, SenderThrowableType extends Throwable>            implements Sender<T, SenderThrowableType> {        final Sender<T, SenderThrowableType> sender;        final Specification<T> specification;        public SpecificationSenderWrapper(Sender<T, SenderThrowableType> sender, Specification<T> specification) {            this.sender = sender;            this.specification = specification;        }        public <ReceiverThrowableType extends Throwable> void sendTo(Receiver<T, ReceiverThrowableType> receiver)                throws ReceiverThrowableType, SenderThrowableType {            sender.sendTo(new SpecificationReceiverWrapper<T, ReceiverThrowableType>(receiver, specification));        }    }    static class SpecificationReceiverWrapper<T, ReceiverThrowableType extends Throwable>            implements Receiver<T, ReceiverThrowableType> {        final Receiver<T, ReceiverThrowableType> receiver;        final Specification<T> specification;        public SpecificationReceiverWrapper(Receiver<T, ReceiverThrowableType> receiver, Specification<T> specification) {            this.receiver = receiver;            this.specification = specification;        }        public void receive(T item) throws ReceiverThrowableType {            if(specification.test(item)) {                receiver.receive(item);            }        }        public void finished() throws ReceiverThrowableType {            receiver.finished();        }    }    public static <T, ReceiverThrowableType extends Throwable> Output<T, ReceiverThrowableType> filter(Specification<T> specification, final Output<T, ReceiverThrowableType> output) {        return new SpecificationOutputWrapper<T, ReceiverThrowableType>(output, specification);    }}

测试代码:

public class Demo_Intercept_FilterLine {    public static void main(String[] args) throws IOException {        File source = new File("in");        File destination = new File("out");        Input<String, IOException> input = Inputs.text(source);        Output<String, IOException> output = Outputs.text(destination);        Specification<String> specification = new Specification<String>() {            public boolean test(String item) {                if(item.trim().length() == 0) return false; // 过滤空行                return true;            }        };        input.transferTo(Filters.filter(specification, output));    }}

第二个常见的操作是把数据从一个类型映射到另一个类型。就是处理要Input和Output的数据类型不同,要有方法把输入数据类型映射成输出的数据类型。下面例子的把String映射成JSONObject,先定义转换方法:

public interface Function<From, To> {    /**     * @return return the transformed data. {@code null} to indicate ignore the input data.      */    To map(From from);}
剩下的基本和上面的类似

public class FunctionFilter {    private FunctionFilter(){}    static class FunctionOutputWrapper<From, To, ReceiverThrowableType extends Throwable>            implements Output<From, ReceiverThrowableType> {        final Output<To, ReceiverThrowableType> output;        final Function<From, To> function;        public FunctionOutputWrapper(Output<To, ReceiverThrowableType> output, Function<From, To> function) {            this.output = output;            this.function = function;        }        public <SenderThrowableType extends Throwable> void receiveFrom(Sender<From, SenderThrowableType> sender)                throws ReceiverThrowableType, SenderThrowableType {            output.receiveFrom(new FunctionSenderWrapper<From, To, SenderThrowableType>(sender, function));        }    }    static class FunctionSenderWrapper<From, To, SenderThrowableType extends Throwable> implements Sender<To, SenderThrowableType> {        final Sender<From, SenderThrowableType> sender;        final Function<From, To> function;        public FunctionSenderWrapper(Sender<From, SenderThrowableType> sender, Function<From, To> function) {            this.sender = sender;            this.function = function;        }        public <ReceiverThrowableType extends Throwable> void sendTo(Receiver<To, ReceiverThrowableType> receiver)                throws ReceiverThrowableType, SenderThrowableType {            sender.sendTo(new FunctionReceiverWrapper<From, To, ReceiverThrowableType>(receiver, function));        }    }    static class FunctionReceiverWrapper<From, To, ReceiverThrowableType extends Throwable>            implements Receiver<From, ReceiverThrowableType> {        final Receiver<To, ReceiverThrowableType> receiver;        final Function<From, To> function;        public FunctionReceiverWrapper(Receiver<To, ReceiverThrowableType> receiver, Function<From, To> function) {            this.receiver = receiver;            this.function = function;        }        public void receive(From item) throws ReceiverThrowableType {            receiver.receive(function.map(item));        }        public void finished() throws ReceiverThrowableType {            receiver.finished();        }    }    public static <From, To, ReceiverThrowableType extends Throwable> Output<From, ReceiverThrowableType> filter(Function<From, To> function, final Output<To, ReceiverThrowableType> output) {        return new FunctionOutputWrapper<From, To, ReceiverThrowableType>(output, function);    }}

测试代码:

public class Demo_Intercept_CountLine {    public static void main(String[] args) throws IOException {        File source = new File("in");        File destination = new File("out");        final AtomicInteger count = new AtomicInteger();        Input<String, IOException> input = Inputs.text(source);        Output<String, IOException> output = Outputs.text(destination);        Function<String, String> function = new Function<String, String>() {            public String map(String from) {                count.incrementAndGet();                return from;            }        };        input.transferTo(FunctionFilter.filter(function, output));        System.out.println("Counter: " + count.get());    }}

转载自:https://github.com/oldratlee/io-api/wiki/generic-io-api-in-java-and-api-design

原创粉丝点击