接口最吸引人的原因之一就是允许同一个接口具有多个不同的具体实现。在简单的情况中,他的体现形式通常是一个接受接口类型的方法,而该接口的实现和向该接口传递的对象则取决于方法的使用者。因此,接口的一种常见用法就是前面提到的策略模式,此时你编写一个执行某些操作的方法,而该方法将接受一个同样是你指定的接口的对象。主要就是要声明“你可以用任何你想要的对象来调用我的方法,只要你的对象遵循我的接口。”这将使得你的方法更加灵活、通用,并更加具有复用性。
例如,Java SE5中的Scanner类的构造器接受的就是一个Readable接口。你会发现Readable没有用作Java标准类库中其他方法的任何参数,他是单独为Scanner创建的,以使得Scanner不必将其参数限定为某个特定类。通过这种方式,Scanner可以作用于更多的类型,如果你创建了一个新的类,并想让Scanner可以作用于他,那么你就应该让他成为Readable。
package filters;
import com.sun.scenario.effect.impl.prism.PrImage;
import java.nio.CharBuffer;
import java.util.Random;
import java.util.Scanner;
public class RandomWords implements Readable {
private static Random rand = new Random(47);
private static final char[] capitals = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();
private static final char[] lowers = "abcdefghijklmnopqrstuvwxyz".toCharArray();
private static final char[] vowels = "aeiou".toCharArray();
private int count;
public RandomWords(int count) {
this.count = count;
}
public int read(CharBuffer cb) {
if (count-- == 0) {
return -1;//Indicates end of input
}
cb.append(capitals[rand.nextInt(capitals.length)]);
for (int i = 0; i < 4; i++) {
cb.append(vowels[rand.nextInt(vowels.length)]);
cb.append(lowers[rand.nextInt(lowers.length)]);
}
cb.append(" ");
return 10;
}
public static void main(String[] atgs) {
Scanner sc = new Scanner(new RandomWords(10));
while (sc.hasNext()) {
System.out.println(sc.next());
}
}
}
Readable接口只要实现read()方法,在read()内部,将输入内容添加到CharBuffer参数中(有很多方法可实现此目的)或者在没有任何输入时返回-1。
假设你有一个还未实现Readable的类,怎么才能让Scanner作用于他呢?下面这个类就是一个例子,他可以产生随机浮点数:
package filters;
import java.util.Random;
public class RandomDoubles {
private static Random rand = new Random(47);
public double next() {
return rand.nextDouble();
}
public static void main(String[] args) {
RandomDoubles rd = new RandomDoubles();
for (int i = 0; i < 7; i++) {
System.out.println(rd.next() + " ");
}
}
}
我们再次使用了适配器模式,但是在本例子中,被适配的类可以通过集成和实现Readable接口来创建。因此,通过使用interface关键字提供的伪多重继承机制,我们可以生成即是RandomDoubles又是Readable的新类。
package filters;
import java.nio.CharBuffer;
import java.util.Scanner;
public class AdapterRandomDoubles extends RandomDoubles implements Readable {
private int count;
public AdapterRandomDoubles(int count) {
this.count = count;
}
public int read(CharBuffer cb) {
if (count-- == 0) {
return -1;
}
String result = Double.toString(next()) + " ";
cb.append(result);
return result.length();
}
public static void main(String[] args) {
new AdapterRandomDoubles(7);
Scanner s = new Scanner(new AdapterRandomDoubles(7));
while (s.hasNext()) {
System.out.println(s.nextDouble() + " ");
}
}
}
因为在这种方式中,我们可以在任何现有之类上添加新的接口,所以这就意味着让方法接受接口类型,是一种让任何类都可以对该方法进行适配的方式。这就是使用接口而不是累的强大之处。