在Effective Java,Item - 18中,Bloch说接口可以防止组合爆炸,这种情况会在类型系统中使用具有多个属性的抽象类时发生。
我无法围绕组合爆炸究竟是什么。
任何人都可以提供组合爆炸的例子,因为使用抽象类,以及如何使用接口来防止这个问题?
答案 0 :(得分:0)
如果类型系统中有n个属性,则可能有2个属性 您可能需要支持的组合。这就是所谓的 组合爆炸。膨胀的类层次结构可能导致膨胀 包含许多方法的类只在其类型上有所不同 论证,因为类层次结构中没有类型可以捕获 共同的行为。
与无法扩展多个类的接口相比,抽象类的一大缺点。
例如,您可以使用接口
public interface Singer {
AudioClip Sing(Song s);
}
public interface Songwriter {
Song compose(boolean hit):
}
public interface SingerSongwriter extends Singer, Songwriter
{
AudioClip strum();
void actSensitive();
}
使用抽象类,您应该执行以下操作:
public abstract class Singer {
abstract AudioClip Sing(Song s);
}
public abstract class Songwriter {
abstract Song compose(boolean hit):
}
public abstract class SingerSongwriter extends Singer
{
abstract AudioClip strum();
abstract void actSensitive();
abstract Song compose(boolean hit):
}
使用抽象类,您Song compose(boolean hit)
重复,并且对此代码的支持非常困难。该系统不如界面使用那么强大。
答案 1 :(得分:0)
注意:此答案来自Software Architecture Design Patterns in Java,有关组合爆炸的示例,请参见装饰器模式一章。
假设您有一个Logger
接口和三个具体的实现:FileLogger
,STDOUTLogger
,DBLogger
。现在想象一下,有3种可能的格式可以记录行:Plain
,HTML
,Encrypted
。
天真的可以为每种可能的组合创建一个类,总计3 * 3 = 9
:
FileLoggerPlain
FileLoggerHtml
FileLoggerEncrypt
STDOUTLoggerPlain
STDOUTLoggerHtml
STDOUTLoggerEncrypt
DBLoggerPlain
DBLoggerHtml
DBLoggerEncrypt
上面的9转换为Java中的9种类型。注意导致支持每种组合的类的激增。您可以改用记录器介质(文件,STDOUT,DB)和格式(普通,HTML,加密)创建可重用类型。请注意,此结果仅包含6种类型。然后,您可以使用Decorator之类的模式将记录器类型包装为格式类型(例如,EncryptLoggerDecorator
包装DBLogger
或包装STDOUTLogger
)以动态更改系统的行为,而不是静态地如果要使用use肿的类层次结构,请定义行为。我相信Joshua Bloch试图推动的重点是保持层次结构平坦,而Java接口为此很好地发挥了自己的作用。