我一直在考虑为我一直在开发的框架提供语法糖的方法。我想专门处理 Immitable 对象。

假设我有一个不可变的对象并希望创建它的修改版本。在您看来,具有单个静态工厂方法的不可实例化类会违反 OO 原则吗?


作为使用字符串的示例:

public final class LOWERCASE {

    private LOWERCASE() {}

    public static String string( final String STRING ) {

      return STRING.toLowerCase();
    }
}

因此,从这个例子我可以写:

String lowercaseString = LOWERCASE.string( targetString );

我觉得很有可读性。


有任何限制条件反对这种方法吗?

有帮助吗?

解决方案

我不认为每个方法创建一个类是个好主意。您可以改为创建一个静态方法类,命名为例如StringUtils并实现这些方法。这样你就可以打电话:

String lowerCaseString = StringUtils.lowercase(targetString);

这也可以在您输入时为您提供智能感知帮助。你的课程列表会变得太大了。即使是这个简单的例子,你也应该实现多个小写类,这样你就可以满足CulutureInfo必须考虑的环境。

我认为这不会以任何方式破坏OO原则或者设计不好。在其他语言中,例如Ruby,您可以将方法直接添加到String类中。结束的方法!表示原始对象已被修改。所有其他方法都返回修改后的副本。 Ruby on Rails框架为String类添加了一些方法,并且对于这是否是一种好技术存在争议。这绝对很方便。

其他提示

通常在不可变对象上,我会有一个方法返回对象的修改版本。因此,如果您有一些不可变集合,它可以有一个sort()方法,它返回一个已排序的新集合。但是,在您的String示例中,这是不可能的,因为您无法触及String类。

您的方法非常易读,我认为对于这样的边缘情况,完全没问题。对于你自己编写的不可变对象,我在对象本身上有方法。

Eric Lippert关于C#中不可变对象的系列文章是顺便说一下,这很好。

在我看来,这样一个工厂类的唯一要点就是该类提供了不同类型的不可变对象。

例如:

public final class Lowercase {

  private Lowercase() {}

  public static String string( final String string ) {

   return new String( string.toLowerCase() );
  }

  public static Foo foo( final Foo f ) {
     boolean isLowerCase = true;
     return new Foo(f, isLowerCase );
  }
}

否则,您应该在不可变类本身中实现您的方法,例如String Class中的toLowerCase()。

无论哪种方式,我认为这不违反任何OO原则。

我同意埃里克的观点。不可变对象应该始终有一个返回对象的修改版本的方法,而不是静态方法。JDK中也有例子:

  • 字符串.subString(int)
  • BigDecimal.movePointLeft(int)

这样做的优点是您不需要将要修改的实例作为方法的参数传递。对于像 String 或 Integer 这样的类,我更喜欢使用包装类。然后您可以控制何时创建此类对象(通过包装类的构造函数或该类的方法之一)。如果您使用 Integer 类,那么控制它就会复杂得多,因为每个人都可以创建它的实例。

另一方面,您的示例被视为一些实用程序类,例如 字符串实用程序 apache commons-lang 包的。看看这个,因为我认为你想创建这样的东西。(不要重新发明轮子)

new String()是代码味道 - 由于 String immutability ,它几乎总是 >。一旦 String 实例具有值,该实例将永远不会有不同的值。

在以下方法中, new String()是多余的:

public static String string( final String string ) {
    return new String( string.toLowerCase() );
}

toLowerCase()返回一个新的(不同的) String 实例 - new String()除了原因之外没有做任何有益的事情另一个对象创建,具有 toLowerCase()返回的 String 实例的确切值

这是一个显示概念的小Groovy脚本(我希望 - 注意,这是脚本语言下的Java):

String a = 'CamelCase'
String b = a.toLowerCase()

println "a='${a}'"
println "b='${b}'"
制造

a='CamelCase'
b='camelcase'

请注意 a 没有改变 - 它是不可变的; b 是一个新的 String 值。

BigDecimal.movePointLeft() BigDecimal 上返回 BigDecimal 的任何其他方法也是如此 - 它们是新实例,保持原始实例不变。

好的,现在回答你的问题:

Strings 执行一组操作,这些操作在您的应用程序中执行一个有用的目的是一个好主意。对于类似 String 的东西,可能不需要使用工厂,但可能需要一些不同的不可变类,需要花费一些精力来构建。

在无法扩展基类的情况下,如 String 静态方法的类描述为@kgiannakakis就可以了。

否则,如果“不可变”, class是应用程序的一部分,您可以访问类声明/定义,返回新实例的方法,在 BigDecimal String 等模型中,将是优选的。这实际上是@Erik Hesselink,@ Bruno Conde和@reallyinsane所说的。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top