我正在阅读Effective Java。在讨论使用函数对象作为策略的部分中,存在以下段落。
因为策略界面可以作为其所有具体策略的类型 实例,不需要公开具体的策略类来输出具体的 战略。相反,“主机类”可以导出公共静态字段(或静态工厂) 方法)其类型是策略接口,具体策略类可以 是主机的私有嵌套类
// Exporting a concrete strategy
class Host {
private static class StrLenCmp
implements Comparator<String>, Serializable {
public int compare(String s1, String s2) {
return s1.length() - s2.length();
}
}
// Returned comparator is serializable
public static final Comparator<String>
STRING_LENGTH_COMPARATOR = new StrLenCmp();
... // Bulk of class omitted
}
我的问题是,使用上述方式有什么特别的优势吗?通过公布具体战略来导出战略有什么问题?
答案 0 :(得分:2)
是的,有。这样你就可以返回接口而不是具体的类,所以如果你改变了Comparator接口的具体实现,你也不必修改客户端类(我认为这是使用接口的最重要原因)。
例如:
//inside aClass
Comparator c = Host.STRING_LENGTH_COMPARATOR; //Programming against interfaces is different from:
StrLenCmp c = Host.STRING_LENGTH_COMPARATOR; //programming against concrete class
假设将来你将使用另一个实现(让我们称之为NewStrLenCmp)更改StrLenCmp,而不是使用针对接口Comparator进行编程而不必修改aClass。
Comparator c = Host.STRING_LENGTH_COMPARATOR; //still work because interface doesn't changed
NewStrLenCmp c = Host.STRING_LENGTH_COMPARATOR; // problem: you need to modify the client class in order to use the new concrete type: bad idea
答案 1 :(得分:2)
与使用任何公开 - 封装相同的问题。
对象的最小可能范围使得更容易推断出如何使用该对象,并且可以大规模地简化维护(您知道private
对象只能在您使用的同一源文件中使用看着,但你真的不知道有多少人使用public
对象或以什么方式使用。
如果您将所有内容声明为公开,那么每个Java程序都可以正常工作。但它有点像潘多拉的盒子 - 一旦你打开了某些东西,就很难把它拿回来。
通过不公开具体策略,您可以阻止其他类/应用程序将其用于自己的目的,这意味着您不必担心将其设计为完全成熟,闪亮,稳定,公共具有明确定义的接口的类。您现在就可以编写适用于 you 的内容,并且知道您可以随意更改它。
答案 2 :(得分:2)
公共内容是您的API。如果您发送代码后来需要更改策略实施,那么您已经为所有发送代码的人有效地破坏了API。
因此,除非另有要求,否则一切都应尽可能在最狭窄的范围内。
我们还将它放入静态嵌套类中,因为我们没有在其他地方使用此策略。