泛型接口

泛型接口的概念

泛型也可以運(yùn)用于接口,例如生成器(generator),這是一種專門負(fù)責(zé)創(chuàng)建對(duì)象的類,實(shí)際上,這是工廠方法設(shè)計(jì)模式的一種應(yīng)用。不過兩者之間不同的是,生成器的調(diào)用不需要任何參數(shù),但是工廠方法一般需要參數(shù)來調(diào)用。這就意味著生成器不需要額外的信息去生成新的對(duì)象。

生成器接口的定義

一般來說,一個(gè)生成器只定義一個(gè)方法,該方法用于產(chǎn)生新的對(duì)象。在這里,就是next()方法。

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

創(chuàng)建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{}

接著我們創(chuàng)建一個(gè)生成器

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

參數(shù)化的Generatoer的接口確保next()的返回值是參數(shù)的類型。CoffeeGenerator同時(shí)還實(shí)現(xiàn)了Iterable接口,所以它可以在ForEach循環(huán)中被使用。不過,它還需要一個(gè)“末端哨兵”來判斷何時(shí)停止,這正是第二個(gè)構(gòu)造器的功能。

創(chuàng)建Fibonacci數(shù)列生成器

下面的類也實(shí)現(xiàn)了Generator<T>接口,它負(fù)責(zé)生成Fibonacci數(shù)列

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類型,但是其參數(shù)類型確是Integer。這是因?yàn)镴ava泛型的局限性:基本類型無法作為類型參數(shù)。但是Java SE5提供了自動(dòng)包裝和拆包的功能,可以很方便地在基本類型和其相應(yīng)的包裝器類型之間進(jìn)行轉(zhuǎn)換。

編寫實(shí)現(xiàn)了Iterable的Fibonacci生成器

如果還想更進(jìn)一步,編寫一個(gè)實(shí)現(xiàn)了Iterable的Fibonacci生成器。一個(gè)選擇是重寫這個(gè)類,令其實(shí)現(xiàn)Iterable接口。
但是我們并不能總是擁有源代碼的控制權(quán),并且,除非必須這么做,否則我們也不愿意重寫一個(gè)類。而且我們還有另一種選擇,就是創(chuàng)建一個(gè)適配器(adapter)來是實(shí)現(xiàn)所需的接口。

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

這里通過使用了繼承來實(shí)現(xiàn)了適配器。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容