Frage

Ich habe für einen Rahmen der Möglichkeiten der Bereitstellung von syntaktischem Zucker denke ich gearbeitet habe. Ich möchte ausschließlich mit Immitable Objekte behandeln.

Sagen, ich habe ein unveränderliches Objekt und wünsche eine modifizierte Version davon zu erstellen. Wäre aus Ihrer Sicht, eine nichtinstanziierbare Klasse mit einem einzigen statischen Factory-Methode Pause OO Prinzipien?


  

Als ein Beispiel unter Verwendung eines String:

public final class LOWERCASE {

    private LOWERCASE() {}

    public static String string( final String STRING ) {

      return STRING.toLowerCase();
    }
}
     

Daher aus diesem Beispiel könnte ich schreiben:

String lowercaseString = LOWERCASE.string( targetString );
     

Was ich sehr gut lesbar finden.


Jede Maßgaben, gegen einen solchen Ansatz?

War es hilfreich?

Lösung

Ich glaube nicht, es ist eine gute Idee, eine Klasse pro Methode zu erstellen. Sie könnten stattdessen eine statische nur Methoden Klasse erstellen, mit dem Namen beispiels StringUtils und die Methoden implementieren. Auf diese Weise würden Sie rufen:

String lowerCaseString = StringUtils.lowercase (targetString);

Dies würde Ihnen auch Intellisense Hilfe, während Sie tippen. Die Liste der Klassen geht sonst zu groß. Auch für dieses einfache Beispiel, sollten Sie mehr als einen Kleinen Klasse implementieren, so dass Sie auch für Umstände sorgen könnten, dass der CulutureInfo in Betracht gezogen werden muß.

Ich glaube nicht, das bricht OO Prinzipien in irgendeiner Weise oder das ist schlechtes Design. In anderen Sprachen Ruby zum Beispiel, könnten Sie Ihre Methoden direkt an String-Klasse hinzufügen. Methoden, die am Ende mit! bedeuten, dass das Original-Objekt modifiziert wird. Alle anderen Methoden liefern eine modifizierte Kopie. Ruby on Rails-Framework fügt einige Methoden der String-Klasse, und es gibt einige Diskussionen darüber, ob dies eine gute Technik ist oder nicht. Es ist aber auf jeden Fall praktisch.

Andere Tipps

In der Regel auf unveränderliche Objekte, würde ich eine Methode, die eine modifizierte Version des Objekts zurück. Also, wenn Sie einige unveränderliche Sammlung haben, kann es eine Art () Methode hat, die eine neue Auflistung zurückgibt, die sortiert wird. Dies ist jedoch in Ihrem String Beispiel ist nicht möglich, da Sie nicht die String-Klasse berühren können.

Ihr Ansatz ist gut lesbar, und ich denke, für die Ränder Fälle wie diesen, ist völlig in Ordnung. Für unveränderliche Objekte Sie selbst schreiben, würde ich die Methode für das Objekt selbst hat.

Eric Lippert Serie auf unveränderliche Objekte in C # ist recht gut, übrigens.

Meiner Meinung nach ist der einzige Punkt einer solchen Fabrik Klasse wäre, wenn die Klasse verschiedene Arten von unveränderliche Objekte zur Verfügung gestellt.

Beispiel:

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 );
  }
}

Andernfalls sollten Sie Ihre Methode in der unveränderlichen Klasse selbst wie toLowerCase () in String-Klasse implementieren.

oder so, ich glaube nicht, das jedes OO-Prinzip bricht.

Ich bin mit Erik. Unveränderliche Objekte sollten immer eine Methode, die eine modifizierte Version des Objekts anstelle einer statischen Methode zurück. Es gibt auch Beispiele im JDK:

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

es auf diese Weise tun hat den Vorteil, dass Sie brauchen nicht die Instanz, die Sie als Argument ändern, für ein Verfahren wollen passieren. Für die Klassen wie String oder Integer würde ich es vorziehen, eine Wrapper-Klasse zu verwenden. Dann können Sie steuern, wenn ein solches Objekt erstellt wird (durch Konstruktor der Wrapper-Klasse oder eine der Methoden der Klasse). Wenn Sie die Klasse Integer verwenden würden es ist viel komplizierter als das jeder zu steuern, kann eine Instanz davon erstellen.

Auf der anderen Seite sind Sie beispielsweise auf einige Utility-Klassen angesehen wird wie StringUtils des apache commons-lang-Paket. Werfen Sie einen Blick auf diese, wie ich denke, dass man so etwas schaffen wollte. (Sie neu erfinden das Rad nicht)

new String() ist ein Code Geruch - es ist fast immer nicht erforderlich, da der Unveränderlichkeit von String. Sobald eine String Instanz einen Wert hat, wird diese Instanz nie, nie einen anderen Wert hat.

In dem folgenden Verfahren new String() ist redundant:

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

toLowerCase() gibt eine neue (andere) String Instanz - new String() nichts tut vorteilhaft hier anders als eine andere Objekterstellung führen durch String den genauen Wert der toLowerCase() Instanz zurückgegeben haben

Hier ist ein kleines Groovy Skript zeigt das Konzept (wie ich hoffe - Notiz, das ist Java unter der Skriptsprache):

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

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

Herstellung

a='CamelCase'
b='camelcase'

Beachten Sie, dass a nicht ändern - es ist unveränderlich; b ist ein neuer String Wert.

Das gleiche gilt für BigDecimal.movePointLeft() oder jede andere Methode auf BigDecimal wahr, die ein BigDecimal zurück - sie neue Instanzen sind, unverändert die ursprüngliche Instanz verlassen

.

OK, jetzt Ihre Frage zu beantworten:

eine Reihe von Operationen für Strings, die einen nützlichen Zweck in Ihrer Anwendung durchführen ist eine gute Idee. wahrscheinlich eine Fabrik zu verwenden ist nicht notwendig, für so etwas wie String, könnte aber für eine andere unveränderliche Klasse sein, das einige Mühe nimmt zu konstruieren.

In dem Fall, wo es nicht möglich ist, die Basisklasse zu erweitern, wie String, eine static methods Klasse wie beschrieben @kgiannakakis ist in Ordnung.

Andernfalls, wenn die „unveränderliche“ Klasse Teil der Anwendung ist, wo Sie Zugriff auf die Klassendeklaration / Definition haben, Methoden eine neue Instanz, im Modell der BigDecimal Rückkehr String, usw., vorzuziehen wären. Dies ist im Wesentlichen, was @Erik Hesselink, @ Bruno Conde und @reallyinsane gesagt hat.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top