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
接口,以及三个具体实现:FileLogger
、STDOUTLogger
、DBLogger
。现在假设有 3 种可能的格式可以记录一行:Plain
、HTML
、Encrypted
.
天真地可以为每个可能的组合创建一个 class,总共 3 * 3 = 9
:
FileLoggerPlain
FileLoggerHtml
FileLoggerEncrypt
STDOUTLoggerPlain
STDOUTLoggerHtml
STDOUTLoggerEncrypt
DBLoggerPlain
DBLoggerHtml
DBLoggerEncrypt
上面的9转化为Java中的9种。请注意 classes 的激增导致支持每个组合。您可以改为创建可重用类型来描述记录器介质(文件、STDOUT、DB)和格式(Plain、Html、Encrypt)。请注意,这只会产生 6 种类型。然后,您可以使用像 Decorator 这样的模式将记录器类型包装在格式类型中(例如 EncryptLoggerDecorator
包装 DBLogger
,或包装 STDOUTLogger
)以动态改变系统的行为,而不是静态的如果要使用臃肿的 class 层次结构,则定义行为。我相信 Joshua Bloch 试图开车回家的要点是保持层次结构平坦,而 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
接口,以及三个具体实现:FileLogger
、STDOUTLogger
、DBLogger
。现在假设有 3 种可能的格式可以记录一行:Plain
、HTML
、Encrypted
.
天真地可以为每个可能的组合创建一个 class,总共 3 * 3 = 9
:
FileLoggerPlain
FileLoggerHtml
FileLoggerEncrypt
STDOUTLoggerPlain
STDOUTLoggerHtml
STDOUTLoggerEncrypt
DBLoggerPlain
DBLoggerHtml
DBLoggerEncrypt
上面的9转化为Java中的9种。请注意 classes 的激增导致支持每个组合。您可以改为创建可重用类型来描述记录器介质(文件、STDOUT、DB)和格式(Plain、Html、Encrypt)。请注意,这只会产生 6 种类型。然后,您可以使用像 Decorator 这样的模式将记录器类型包装在格式类型中(例如 EncryptLoggerDecorator
包装 DBLogger
,或包装 STDOUTLogger
)以动态改变系统的行为,而不是静态的如果要使用臃肿的 class 层次结构,则定义行为。我相信 Joshua Bloch 试图开车回家的要点是保持层次结构平坦,而 Java 界面非常适合这个目的。