java:函数对象作为策略

发布于 2024-12-13 23:59:04 字数 739 浏览 7 评论 0原文

我正在阅读《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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

云淡月浅 2024-12-20 23:59:04

是的,有。这样您将返回接口而不是具体类,因此如果您更改 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

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:

//inside aClass

Comparator c = Host.STRING_LENGTH_COMPARATOR; //Programming against interfaces is different from:
StrLenCmp  c = Host.STRING_LENGTH_COMPARATOR; //programming against concrete class

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.

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
孤云独去闲 2024-12-20 23:59:04

这与将任何东西公开 - 封装是同样的问题。

对象的尽可能窄的范围使得更容易推断该对象的使用方式,并且可以极大地简化维护(您知道 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 a public 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.

尘曦 2024-12-20 23:59:04
  • 公共内容您的 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文