Java 中的组合爆炸示例?

Examples for combinatorial explosion in Java?

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

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

任何人都可以提供一个因为使用抽象类而导致组合爆炸的例子,以及如何使用接口来防止这个问题?

If there are n attributes in the type system, there are 2n possible combinations that you might have to support. This is what’s known as a combinatorial explosion. Bloated class hierarchies can lead to bloated classes containing many methods that differ only in the type of their argu- ments, as there are no types in the class hierarchy to capture common behaviors.

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

例如,您可以使用接口

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) 重复,并且此代码的​​支持非常困难。这个系统不如使用界面那么健壮。

注意:此答案借鉴自 Software Architecture Design Patterns in Java,有关组合爆炸的示例,请参阅装饰模式章节。

假设你有一个Logger接口,以及三个具体实现:FileLoggerSTDOUTLoggerDBLogger。现在假设有 3 种可能的格式可以记录一行:PlainHTMLEncrypted.

天真地可以为每个可能的组合创建一个 class,总共 3 * 3 = 9:

  1. FileLoggerPlain
  2. FileLoggerHtml
  3. FileLoggerEncrypt
  4. STDOUTLoggerPlain
  5. STDOUTLoggerHtml
  6. STDOUTLoggerEncrypt
  7. DBLoggerPlain
  8. DBLoggerHtml
  9. DBLoggerEncrypt

上面的9转化为Java中的9种。请注意 classes 的激增导致支持每个组合。您可以改为创建可重用类型来描述记录器介质(文件、STDOUT、DB)和格式(Plain、Html、Encrypt)。请注意,这只会产生 6 种类型。然后,您可以使用像 Decorator 这样的模式将记录器类型包装在格式类型中(例如 EncryptLoggerDecorator 包装 DBLogger,或包装 STDOUTLogger)以动态改变系统的行为,而不是静态的如果要使用臃肿的 class 层次结构,则定义行为。我相信 Joshua Bloch 试图开车回家的要点是保持层次结构平坦,而 Java 界面非常适合这个目的。