Java Generics:将通用函数对象链接在一起

dow*_*ner 6 java generics chain-of-responsibility

我一直在努力解决以下问题.我有一系列函数对象,每个函数对象都有自己的输入和输出类型,通过java中的泛型类型参数定义.我想在链中安排这些,以便将原始数据输入到第一个函数,转换为输出类型,这是下一个对象的输入类型,依此类推.当然这对于硬编码来说是微不足道的,但是我想让代码可以插入到新的函数对象中.如果我只是省略类型参数(只有最终的输出类型),这就是事情的样子:

    public T process() {
        Iterator<Context> it = source.provideData();
        for(Pipe pipe : pipeline) {
            it = pipe.processIterator(it);
        }
        return sink.next(it);
    }
Run Code Online (Sandbox Code Playgroud)

这里,数据上的迭代器在函数对象之间传递,上下文应该是Context.有没有办法保持以下类型的管道可插拔,仍然保持类型安全?

编辑:为了清楚起见,我有一系列功能对象,管道.每个都将特定类型作为输入,并输出另一种类型.(实际上是这些类型的迭代器)这些将被链接在一起,例如Pipe<A,B> -> Pipe<B,C> -> Pipe<C,D> -> ...,以便一个管道的输出是下一个管道的输入类型.这里还有一个源,它输出一个类型为A的迭代器,以及一个接受类型的接收器(过去管道的输出).这会让事情更清楚吗?问题是,因为输入和输出类型的兼容性存在严重依赖性,有没有办法确保这一点?

我开始认为将函数对象插入管道可能是确保类型安全的最佳时间,但我不知道如何做到这一点.

编辑2:我有一个函数对象的加法器方法,如下所示:

public void addPipe(Pipe<?,?> pipe) {
    pipeline.add(pipe);
}
Run Code Online (Sandbox Code Playgroud)

我想检查第一个类型参数是否与当前管道的"结束"相同,如果没有则抛出异常?我不认为这里有一个很好的方法来获得编译时安全性.然后可以将当前管道的"结束"设置为输入管道的第二个类型参数.我想不出如何用泛型来做这件事,并且传递类信息似乎很可怕.

JB *_*zet 10

这是一种方法.run方法不是类型安全的,但考虑到附加管道的唯一方法是以类型安全的方式进行,整个链是类型安全的.

public class Chain<S, T> {
    private List<Pipe<?, ?>> pipes;

    private Chain() {
    }

    public static <K, L> Chain<K, L> start(Pipe<K, L> pipe) {
        Chain<K, L> chain = new Chain<K, L>();
        chain.pipes = Collections.<Pipe<?, ?>>singletonList(pipe);;
        return chain;
    }

    public <V> Chain<S, V> append(Pipe<T, V> pipe) {
        Chain<S, V> chain = new Chain<S, V>();
        chain.pipes = new ArrayList<Pipe<?, ?>>(pipes);
        chain.pipes.add(pipe);
        return chain;
    }

    @SuppressWarnings({ "rawtypes", "unchecked" })
    public T run(S s) {
        Object source = s;
        Object target = null;
        for (Pipe p : pipes) {
            target = p.transform(source);
            source = target;
        }
        return (T) target;
    }

    public static void main(String[] args) {
        Pipe<String, Integer> pipe1 = new Pipe<String, Integer>() {
            @Override
            public Integer transform(String s) {
                return Integer.valueOf(s);
            }
        };
        Pipe<Integer, Long> pipe2 = new Pipe<Integer, Long>() {
            @Override
            public Long transform(Integer s) {
                return s.longValue();
            }
        };
        Pipe<Long, BigInteger> pipe3 = new Pipe<Long, BigInteger>() {
            @Override
            public BigInteger transform(Long s) {
                return new BigInteger(s.toString());
            }
        };
        Chain<String, BigInteger> chain = Chain.start(pipe1).append(pipe2).append(pipe3);
        BigInteger result = chain.run("12");
        System.out.println(result);
    }
}
Run Code Online (Sandbox Code Playgroud)