Java中的组合爆炸示例?

Java中的组合爆炸示例?,java,effective-java,Java,Effective Java,在有效的Java项目-18中,Bloch说接口可以防止组合爆炸,在类型系统中使用具有多个属性的抽象类时会发生组合爆炸 我无法理解什么是组合爆炸 谁能提供一个使用抽象类的组合爆炸的例子,以及如何使用接口来防止这个问题 如果类型系统中有n个属性,则可能有2n个 您可能必须支持的组合。这就是所谓的 组合爆炸。臃肿的类层次结构可能导致臃肿 包含许多方法的类,这些方法只在其 参数,因为类层次结构中没有要捕获的类型 常见行为 与不能扩展多个类的接口相比,抽象类的一大缺点是它不能扩展多个类 例如,使用您可以执

在有效的Java项目-18中,Bloch说接口可以防止组合爆炸,在类型系统中使用具有多个属性的抽象类时会发生组合爆炸

我无法理解什么是组合爆炸

谁能提供一个使用抽象类的组合爆炸的例子,以及如何使用接口来防止这个问题

如果类型系统中有n个属性,则可能有2n个 您可能必须支持的组合。这就是所谓的 组合爆炸。臃肿的类层次结构可能导致臃肿 包含许多方法的类,这些方法只在其 参数,因为类层次结构中没有要捕获的类型 常见行为

与不能扩展多个类的接口相比,抽象类的一大缺点是它不能扩展多个类

例如,使用您可以执行的接口

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):
}

对于抽象类,您有
歌曲合成(布尔命中)
复制,并且支持此代码非常困难。此系统不如使用接口时那么健壮。

注意:此答案借用了,有关组合爆炸的示例,请参见装饰图案一章

假设您有一个
Logger
接口和三个具体实现:
FileLogger
STDOUTLogger
DBLogger
。现在假设有3种可能的格式可以记录一行代码:
普通的
HTML
加密的

很自然,我们可以为每个可能的组合创建一个类,其总数
3*3=9

  • FileLoggerPlain
  • FileLoggerHtml
  • FileLoggerEncrypt
  • STDOUTLoggerPlain
  • STDOUTLoggerHtml
  • STDOUTLoggerEncrypt
  • DBLoggerPlain
  • DBLoggerHtml
  • DBLoggerEncrypt

  • 上面的9在Java中转换为9种类型。注意支持每种组合的类的激增。您可以创建可重用的类型来描述记录器介质(文件、标准输出、数据库)和格式(普通、Html、加密)。请注意,这只会导致6种类型。然后,您可以使用类似Decorator的模式将记录器类型包装为格式类型(例如,
    EncryptLoggerDecorator
    wrapps
    DBLogger
    ,或wrapps
    STDOUTLogger
    ),以动态改变系统的行为,而不是在使用臃肿的类层次结构时静态定义行为。我相信Joshua Bloch试图强调的一点是保持层次结构的扁平化,Java接口很适合这个目的。

    或者可以使用组合:一个Logger类,带有两个字段,类似:
    LogFormatter
    (将是
    PlainFormatter
    HtmlFormatter
    EncryptedFormatter
    中的一个)加上
    LogWriter