1

私が取り組んでいるフレームワークに構文糖衣を提供する方法を考えてきました。Immitable オブジェクトのみを扱いたい。

不変オブジェクトがあり、それを変更したバージョンを作成したいとします。あなたの見解では、単一の静的ファクトリ メソッドを持つインスタンス化不可能なクラスは OO の原則を破りますか?


文字列を使用した例として:

public final class LOWERCASE {
  
    private LOWERCASE() {}
  
    public static String string( final String STRING ) {
   
      return STRING.toLowerCase();
    }
}

したがって、この例から次のように書くことができます。

String lowercaseString = LOWERCASE.string( targetString );

とても読みやすいと思います。


そのようなアプローチに対する何らかの但し書きはありますか?

4

5 に答える 5

4

メソッドごとに 1 つのクラスを作成するのは得策ではないと思います。代わりに、StringUtils などの名前の静的メソッドのみのクラスを作成し、メソッドを実装することもできます。このようにして、次のように呼び出します。

String lowerCaseString = StringUtils.lowercase( targetString );

これにより、入力中にインテリセンスのヘルプも提供されます。そうしないと、クラスのリストが大きくなりすぎます。この単純な例であっても、CulutureInfo を考慮しなければならない状況にも対応できるように、複数の Lowercase クラスを実装する必要があります。

これが OO の原則に違反しているとは思いませんし、設計が悪いとは思いません。Ruby などの他の言語では、メソッドを String クラスに直接追加できます。! で終わるメソッド 元のオブジェクトが変更されたことを示します。他のすべてのメソッドは、変更されたコピーを返します。Ruby on Rails フレームワークは String クラスにいくつかのメソッドを追加しますが、これが良い手法かどうかについてはいくつかの議論があります。便利なのは間違いないけど。

于 2008-11-11T12:11:53.723 に答える
1

new String()はコードの臭いです-の不変性のため、ほとんどの場合不要です。インスタンスに値が設定されると、そのインスタンスに異なる値が設定されることはありません。StringString

次の方法では、new String()は冗長です。

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

toLowerCase()新しい(異なる)Stringインスタンスを返します-ここでは、によって返されるインスタンスnew String()の正確な値を持つ別のオブジェクトを作成する以外に、有益なことは何もしません。StringtoLowerCase()

これが概念を示す小さなGroovyスクリプトです(私は願っています-注意してください、これはスクリプト言語の下でのJavaです):

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

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

生産

a='CamelCase'
b='camelcase'

a 変更されていないことに注意してください-それは不変です。 bは新しいString値です。

同じことが、またはを返すBigDecimal.movePointLeft()他のメソッドにも当てはまります。これらは新しいインスタンスであり、元のインスタンスは変更されません。BigDecimalBigDecimal

さて、あなたの質問に答えましょう:

アプリケーションで有用な目的を実行するための一連の操作を用意Stringsすることは良い考えです。ファクトリを使用することは、のようなものにはおそらく必要ありStringませんが、構築するのにいくらかの努力を要する別の不変のクラスには必要かもしれません。

のように基本クラスを拡張できない場合は、@kgiannakakisで説明されてStringいるsクラスで問題ありません。static method

それ以外の場合、「不変」クラスがアプリケーションの一部であり、クラスの宣言/定義にアクセスできる場合は、、などのモデルで新しいインスタンスを返すメソッドBigDecimalString適しています。これは本質的に、@ Erik Hesselink、@ Bruno Conde、@reallyinsaneが言ったことです。

于 2008-11-11T13:25:10.750 に答える
1

通常、不変オブジェクトでは、オブジェクトの変更されたバージョンを返すメソッドがあります。したがって、不変のコレクションがある場合は、並べ替えられた新しいコレクションを返す sort() メソッドを持つことができます。ただし、 String の例では、 String クラスに触れることができないため、これは不可能です。

あなたのアプローチは非常に読みやすく、このようなエッジケースでは完全に問題ないと思います。自分で作成する不変オブジェクトの場合、オブジェクト自体にメソッドがあります。

ちなみに、 C# の不変オブジェクトに関する Eric Lippert のシリーズは非常に優れています。

于 2008-11-11T12:03:33.193 に答える
1

私の意見では、そのようなファクトリ クラスの唯一のポイントは、クラスがさまざまな種類の不変オブジェクトを提供する場合です。

元:

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 クラスの toLowerCase() のように、不変クラス自体にメソッドを実装する必要があります。

いずれにせよ、これがOOの原則に違反しているとは思いません。

于 2008-11-11T12:25:42.290 に答える
1

私はエリックに同意します。不変オブジェクトには、静的メソッドではなく、オブジェクトの変更されたバージョンを返すメソッドが常に必要です。JDK にも例があります。

  • String.subString(int)
  • BigDecimal.movePointLeft(int)

このようにすると、変更するインスタンスをメソッドの引数として渡す必要がないという利点があります。String や Integer などのクラスには、ラッパー クラスを使用することをお勧めします。次に、そのようなオブジェクトがいつ作成されるかを制御できます (ラッパー クラスのコンストラクターまたはクラスのメソッドの 1 つによって)。クラス Integer を使用すると、誰もがそのインスタンスを作成できるため、これを制御するのははるかに複雑になります。

一方、あなたの例は、Apache commons-lang パッケージのStringUtilsのようないくつかのユーティリティ クラスと見なされます。このようなものを作りたかったので、これを見てください。(車輪の再発明はしないでください)

于 2008-11-11T12:28:11.227 に答える