java:函数对象作为策略
我正在阅读《Effective Java》。在讨论使用函数对象作为策略的部分中,存在以下段落。
因为策略接口充当其所有具体策略的类型 例如,不需要公开具体的策略类来导出具体的策略类 战略。相反,“主机类”可以导出公共静态字段(或静态工厂) method),其类型为策略接口,具体策略类可以 是主机的私有嵌套类
// 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
}
我的问题是,使用上述方式有什么特别的优点吗?通过公开具体战略来输出战略有什么问题?
I am reading Effective Java. In a section that talks about using function objects as strategies, the below paragraph is present.
Because the strategy interface serves as a type for all of its concrete strategy
instances, a concrete strategy class needn’t be made public to export a concrete
strategy. Instead, a “host class” can export a public static field (or static factory
method) whose type is the strategy interface, and the concrete strategy class can
be a private nested class of the host
// 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
}
My question is , is there any particular advantage of using the above way? What is the problem with exporting the strategy by making concrete strategy public?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
是的,有。这样您将返回接口而不是具体类,因此如果您更改 Comparator 接口的具体实现,则不必也修改客户端类(我认为这是使用接口的最重要原因)。
例如:
假设将来您将使用另一个实现(让我们称之为 NewStrLenCmp)更改 StrLenCmp,那么如果您针对接口 Comparator 进行编程,则无需修改 aClass。
Yes, there is. This way you are returning the interface and not the concrete class, so if you change the concrete implementation of Comparator interface you don't have to modify client classes too (I think this is the most important reason of using interfaces).
For example:
Suppose in the future you will change StrLenCmp with another implementation (let's call it NewStrLenCmp) than if you have programmed against interface Comparator you don't have to modify aClass.
这与将任何东西公开 - 封装是同样的问题。
对象的尽可能窄的范围使得更容易推断该对象的使用方式,并且可以极大地简化维护(您知道
private
对象只能在您所在的同一源文件中使用)看着,但你永远无法真正知道有多少人正在使用public
对象或以什么方式使用)。当然,如果您将所有内容都声明为公共,那么每个 Java 程序都可以运行。但这有点像潘多拉魔盒——一旦你打开了对某些东西的访问权,就很难将其收回。
通过不公开具体策略,您可以防止其他类/应用程序将其用于自己的目的,这意味着您不必担心将其设计为一个成熟的、闪亮的、稳定的公共类,并且具有定义明确的界面。您现在就可以编写对您有用的内容,并且知道以后您可以自由地根据需要进行更改。
It's the same problem as making anything public - encapsulation.
The narrowest possible scope for an object makes it much easier to reason about how that object is used, and can ease maintenance massively (you know a
private
object can only be used in the same source file you're looking at, but you can never truly know how many people are using apublic
object or in what ways).Every Java program would work if you declared everything as public, sure. But it's a bit like Pandora's box - once you've opened up access to something, it's hard to take it back.
By not making the concrete strategy public, you prevent other classes/apps being able to use it for their own purposes, which means you don't have to worry about designing it as a fully-fledged, shiny, stable, public class with a well-defined interface. You can just write what works for you, right now, and know that you have the freedom to change it however you want later.
公共内容是您的 API。如果您发布了代码,后来需要更改策略实现,那么您实际上已经破坏了您向其发送代码的每个人的 API。
因此,除非另有要求,一切都应在尽可能狭窄的范围内。
我们还将其放入静态嵌套类中,因为我们没有在其他地方使用此策略。
Public stuff is your API. If you ship your code and later need to change your strategy implementation, you have effectively broken your API for everyone you shipped code to.
So until otherwise required, everything should be in the narrowest scope possible.
We also put it into a static nested class because we aren't using this strategy elsewhere.