美文网首页
泛型接口

泛型接口

作者: 呆呆李宇杰 | 来源:发表于2017-09-10 00:29 被阅读64次

    泛型接口的概念

    泛型也可以运用于接口,例如生成器(generator),这是一种专门负责创建对象的类,实际上,这是工厂方法设计模式的一种应用。不过两者之间不同的是,生成器的调用不需要任何参数,但是工厂方法一般需要参数来调用。这就意味着生成器不需要额外的信息去生成新的对象。

    生成器接口的定义

    一般来说,一个生成器只定义一个方法,该方法用于产生新的对象。在这里,就是next()方法。

    public interface Generator<T> {
        T next();
    }
    

    创建Coffee生成器

    首先我们需要一些类以供生成

    // Coffee.java
    public class Coffee {
        private static long counter = 0;
        private final long id = counter++;
    
        @Override
        public String toString() {
            return getClass().getSimpleName() + " " + id;
        }
    }
    
    // Latte.java
    public class Latte extends Coffee{}
    
    // Mocha.java
    public class Mocha extends Coffee{}
    
    // Cappuccino.java
    public class Cappuccino extends Coffee{}
    
    // Americano.java
    public class Americano extends Coffee{}
    
    // Breve.java
    public class Breve extends Coffee{}
    

    接着我们创建一个生成器

    public class CoffeeGenerator implements Generator<Coffee>, Iterable<Coffee> {
    
        private Class[] types = {Latte.class, Mocha.class, Cappuccino.class, Americano.class, Breve.class};
    
        private Random rand = new Random(47);
    
        public CoffeeGenerator() {
        }
    
        private int size = 0;
    
        public CoffeeGenerator(int size) {
            this.size = size;
        }
    
        @Override
        public Coffee next() {
            try {
                return (Coffee) types[rand.nextInt(types.length)].newInstance();
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    
        class CoffeeIterator implements Iterator<Coffee> {
    
            int count = size;
    
            public boolean hasNext() {
                return count > 0;
            }
    
            @Override
            public Coffee next() {
                count--;
                return CoffeeGenerator.this.next();
            }
    
            @Override
            public void remove() {
                throw new UnsupportedOperationException();
            }
        }
    
        @Override
        public Iterator<Coffee> iterator() {
            return new CoffeeIterator();
        }
    
        public static void main(String[] args) {
            CoffeeGenerator gen = new CoffeeGenerator();
            for (int i = 0; i < 5; i++) {
                System.out.println("gen.next() = " + gen.next());
            }
            for (Coffee coffee : new CoffeeGenerator(5)) {
                System.out.println("coffee = " + coffee);
            }
        }
    }
    
    // Outputs
    gen.next() = Americano 0
    gen.next() = Latte 1
    gen.next() = Americano 2
    gen.next() = Mocha 3
    gen.next() = Mocha 4
    coffee = Americano 5
    coffee = Latte 6
    coffee = Americano 7
    coffee = Mocha 8
    coffee = Mocha 9
    

    参数化的Generatoer的接口确保next()的返回值是参数的类型。CoffeeGenerator同时还实现了Iterable接口,所以它可以在ForEach循环中被使用。不过,它还需要一个“末端哨兵”来判断何时停止,这正是第二个构造器的功能。

    创建Fibonacci数列生成器

    下面的类也实现了Generator<T>接口,它负责生成Fibonacci数列

    public class Fibonacci implements Generator<Integer> {
    
        private int count = 0;
    
        public Integer next() {
            return fib(count++);
        }
    
        private int fib(int n) {
            if (n < 2) {
                return 1;
            }
            return fib(n - 2) + fib(n - 1);
        }
    
        public static void main(String[] args) {
            Fibonacci gen = new Fibonacci();
            for (int i = 0; i < 18; i++) {
                System.out.print(gen.next() + " ");
            }
        }
    }
    
    // Outputs
    1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584
    

    这里注意到,虽然在Fibonacci里面使用的都是int类型,但是其参数类型确是Integer。这是因为Java泛型的局限性:基本类型无法作为类型参数。但是Java SE5提供了自动包装和拆包的功能,可以很方便地在基本类型和其相应的包装器类型之间进行转换。

    编写实现了Iterable的Fibonacci生成器

    如果还想更进一步,编写一个实现了Iterable的Fibonacci生成器。一个选择是重写这个类,令其实现Iterable接口。
    但是我们并不能总是拥有源代码的控制权,并且,除非必须这么做,否则我们也不愿意重写一个类。而且我们还有另一种选择,就是创建一个适配器(adapter)来是实现所需的接口。

    public class IterableFibonacci extends Fibonacci implements Iterable<Integer> {
    
        private int n;
    
        public IterableFibonacci(int count) {
            this.n = count;
        }
    
        @Override
        public Iterator<Integer> iterator() {
            return new Iterator<Integer>() {
                @Override
                public boolean hasNext() {
                    return n > 0;
                }
    
                @Override
                public Integer next() {
                    n--;
                    return IterableFibonacci.this.next();
                }
    
                @Override
                public void remove() {
                    throw new UnsupportedOperationException();
                }
            };
        }
    
        public static void main(String[] args) {
            for (int i : new IterableFibonacci(18)) {
                System.out.print(i + " ");
            }
        }
    }
    
    // Outputs
    1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584
    

    这里通过使用了继承来实现了适配器。

    相关文章

      网友评论

          本文标题:泛型接口

          本文链接:https://www.haomeiwen.com/subject/djxzjxtx.html