这个问题得到了一些否决,因为从某种意义上来说,它有点基本,但我认为它实际上有点有趣。毕竟,像这样的工厂类Executors
在您的示例中,可以指定它返回Executor
s。但是,正如您所指出的,这只是一个接口,您实际上需要一个实例实施 Executor
如果您能够调用这些方法。为什么工厂不必告诉我们退回物品的实际类型?
如果您以前没有见过这个,可能不清楚如何做这样的事情。要记住的重要一点是,如果您有一个实现接口的类,那么声明为返回接口类型的方法可以返回该类的实例。也就是说,你可以这样做:
interface Foo { /* ... */ }
class Bar implements Foo { /* ... */ }
class Factory {
Foo makeFoo() {
return new Bar( /*... */ );
}
}
makeFoo
被声明返回一个Foo
, but Foo
是一个接口;你实际上无法拥有它的实例。您只能拥有以下类的实例实施 Foo
. Bar
确实实施Foo
,所以你可以返回一个实例Bar
.
我们可以这样做的原因是,当需要调用对象上的方法时,该方法的实现是在我们引用的实际对象中找到的。查找方法的方式实际上有点复杂。但从概念上讲,你可能会这样想:如果你告诉我你是一个Foo
,然后我可以要求您运行中声明的任何方法Foo
, but you准确地决定您对该方法做什么。我只能用你的Foo
输入确定我可以要求您执行哪些方法。这非常重要,也是为什么我们可以重写子类中的方法。这些被称为虚拟方法。这如此重要的原因之一是,它使我们能够使用接口,在其中我们可以透露有关我们的实现的最少量信息(我们可以选择说“我实现Foo
,但这就是我告诉你的关于我自己的全部),但仍然遵守合同(即,我保证实际实现中声明的所有方法Foo
).
下面的示例更深入一些,并捕获了您所看到的更多工厂模式Executors.
Code
public class InterfacesExample {
/**
* An interface with one method.
*/
interface Frobber {
/**
* Frob the object.
* @param object the object
*/
void frob( Object object );
}
/**
* A factory class with one method for creating printing frobber.
*/
public static class Frobbers {
/**
* Returns a Frobber whose {@link Frobber#frob(Object)} method
* prints its argument
* @return a printing Frobber
*/
public static Frobber newPrintingFrobber() {
// This returns an instance of an anonymous class
// that implements the Frobber interface. It has
// to provide an implementation of frob(Object),
// though.
return new Frobber() {
@Override
public void frob( final Object object ) {
System.out.println( "Frobbing "+object+"..." );
}
};
}
/**
* Returns a Frobber whose {@link Frobber#frob(Object)} method
* prints the prefix and its argument
* @param prefix an object
* @return a prefixing printing Frobber
*/
public static Frobber newPrefixingPrintingFrobber( final Object prefix ) {
return new PrefixingPrintingFrobber( prefix );
}
/**
* A private, but not anonymous class. Instances shouldn't be
* made with its constructor, but rather through the factory
* method {@link Frobbers#newPrefixingPrintingFrobber(Object)}.
*/
private static class PrefixingPrintingFrobber implements Frobber {
final Object prefix;
public PrefixingPrintingFrobber( Object prefix ) {
this.prefix = prefix;
}
@Override
public void frob( final Object object ) {
System.out.println( "Frobbing "+prefix+":"+object+"..." );
}
}
}
/**
* Create some frobbers with the factory and test them out.
*/
public static void main( final String[] args ) {
final Frobber f1 = Frobbers.newPrintingFrobber();
f1.frob( 42 );
final Frobber f2 = Frobbers.newPrefixingPrintingFrobber( "boing" );
f2.frob( 36 );
}
}
Output
Frobbing 42...
Frobbing boing:36...