3

我正在阅读有效的 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
  }        

我的问题是,使用上述方式有什么特别的优势吗?通过公开具体战略来输出战略有什么问题?

4

3 回答 3

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
于 2011-11-03T10:27:25.120 回答
2

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

对象的最窄范围可以更容易地推断该对象的使用方式,并且可以大大简化维护(您知道private对象只能在您正在查看的同一源文件中使用,但您永远无法真正知道有多少人在使用一个public对象或以什么方式使用)。

当然,如果您将所有内容都声明为公共,那么每个 Java 程序都可以工作。但这有点像潘多拉的盒子——一旦你打开了对某些东西的访问权限,就很难收回它。

通过不公开具体策略,您可以防止其他类/应用程序将其用于自己的目的,这意味着您不必担心将其设计为一个成熟的、闪亮的、稳定的、具有定义明确的界面。您可以立即编写适合的内容,并且知道您以后可以随意更改它。

于 2011-11-03T10:27:57.107 回答
2
  • 公共的东西你的 API。如果您交付代码后需要更改策略实施,那么您实际上破坏了您向其交付代码的每个人的 API。

  • 因此,除非另有要求,否则一切都应尽可能在最窄的范围内。

  • 我们还将它放入静态嵌套类中,因为我们没有在其他地方使用这种策略。

于 2011-11-03T10:30:33.580 回答