2009-04-15 12 views
5

Ich bin in diesem Projekt beteiligt, wo wir auf guten Teil des alten Codes aufbauen. Ich habe eine besondere Situation in Bezug auf ein großes Java-Objekt, das über Draht übertragen werden muss. Also mein erster Gedanke war, es unveränderlich und serializable machen den Trick zu tun .Bei diesem Punkt, den ich mit einigen schwierigen Entscheidungen konfrontiert bin: -Erstellen von unveränderlichen Objekten von Javabean

  1. Idealerweise möchte ich einen Weg automatisch eine unveränderliche, serializable erzeugen Version dieser Klasse. Ich habe nicht den Umfang zu refactor oder diese Klasse in irgendeiner Weise zu ändern und ich würde wirklich wirklich hassen, um kopieren einfügen die Klasse mit einem anderen Namen ?

  2. Unter der Annahme, dass i auf 1, dh bis gab wählte ich tatsächlich Code von duplizieren der riesige javabean Klasse, ich habe noch in der unappetitliche Situation sein wird der Konstruktor mit einigen 20-25 Parameter zu schreiben zu machen diese Klasse unveränderlich. Was ist ein besserer Weg, um eine Klasse unveränderlich andere als Konstruktor-Injektion zu machen?

Danke und Grüße,

+0

Das ist eine sehr gute Frage. Es sei denn, Sie haben eine doppelte unveränderliche Klasse - es scheint keinen wirklich guten Weg zu geben, dies zu lösen. Ich habe die effektiv unveränderliche Methode benutzt! – Fortyrunner

Antwort

4

Um es wirklich unveränderlich zu machen, müssen Sie die Mitglieder an Bauzeiten initialisieren.

Ein Weg (und ich sage nicht, es ist hübsch!), Dies zu tun und eine riesige Parameterliste im Konstruktor zu vermeiden, ist ein veränderbarer Typ mit denselben Eigenschaften. Legen Sie die Eigenschaften für den veränderbaren Typ nacheinander über "Setter" fest und übergeben Sie das veränderbare Objekt dann als einzelnes Argument an den Konstruktor des unveränderlichen Typs. Das unveränderliche Objekt kopiert dann die Eigenschaften von der veränderbaren Quelle in eigene (final) Mitglieder.

Sie könnten auch "effektive Unveränderlichkeit" in Betracht ziehen. Das heißt, obwohl die Unveränderbarkeit vom System nicht erzwungen wird, verwenden Sie Codierungsmethoden, die die Initialisierungsphase klar von der Nutzungsphase trennen. Immerhin ist die Unveränderlichkeit für die Serialisierung nicht erforderlich.

Sie können einen Schritt weiter gehen, indem Sie einen Implementierungs-Wrapper für die Schnittstelle erstellen, der die Eigenschaften der Implementierung nicht verfügbar macht. Der Wrapper implementiert nur die Methoden in der Schnittstelle, indem er an die "echte" Implementierung delegiert. Die Setter und Getter der Implementierung sind im Wrapper nicht vorhanden. Dadurch wird verhindert, dass Clients einfach von der Schnittstelle zur Implementierungsklasse wechseln und die Eigenschaften manipulieren.

+0

können Sie für jedes Szenario ein Codebeispiel hinzufügen, versuchen, es zu verstehen und es schwer zu haben. – Rachel

1

20-25 Eigenschaften ist nicht riesig für eine einmalige, vor allem, wenn Sie einen halbwegs anständigen Editor verwenden.

Wenn Sie bereits eine veränderbare Instanz beim Erstellen der unveränderbaren Version haben, übergeben Sie diese einfach an den Konstruktor.

Wenn Sie wirklich böser Hacky, seine java.beans verwenden, um ein serialisable Map für die veränderbare Klasse oder Unterklasse Externalizable Implementierung zu erstellen. Alternativ können Sie auch java.beans XML-Serialisierung verwenden (das XML, das über Java-Serialisierung gesendet werden kann ...).

0

Schritt 1: Erstellen Sie eine neue Klasse und geben Sie ihr Instanzvariablen mit genau den gleichen Namen wie die Instanzvariablen Ihres 'großen Java-Objekts'. Diese neue Klasse sollte keine Setter haben (sondern nur Getters), um sie unveränderlich zu machen.

Schritt 2: Verwenden Sie Apache Commons BeanUtils.copyProperties alle Eigenschaften kopieren (das heißt Instanzvariablen) von Ihrem ‚großen Java-Bean-Objekt‘ zu Ihrem neuen Objekt.

0

Einige Ideen:

Geschützte Setter und Fabrikmethoden Sie Bohnen mit geschützten Setter-Methoden und in der gleichen Paket eine Factory-Klasse definieren, die alle Parameter nimmt und ruft diese Setter. Die Bean ist außerhalb dieses Pakets unveränderbar. Um dies zu erzwingen, versiegeln Sie Ihr Jar, damit Endbenutzer keine neuen Klassen im selben Paket erstellen können.

Hinweis: Sie können meine JavaDude Bean Annotationen verwenden, um die Erstellung einfacher zu machen: http://code.google.com/p/javadude/wiki/Annotations

Zum Beispiel:

@Bean(writer=Access.PROTECTED, // all setXXX methods will be protected 
    properties={ 
     @Property(name="name"), 
     @Property(name="age", type=int.class) 
    }) 
public class Person extends PersonGen { 
} 

Erstellen von Getter und einem Konstruktor in Eclipse

Eklipse hat einige nette Werkzeuge, um das schnell zu machen:

  1. Erstellen Sie die Bean-Klasse
  2. Fügen Sie die gewünschten Felder
  3. im Editorfenster die „Select Getter“
  4. Taste
  5. Wählen Sie Quelle-> Gene Getter und Setter
  6. Drücken Sie die rechte Maustaste drücken ok
  7. Rechtsklicken Sie im Editorfenster
  8. Quelle-> wählen Sie generieren Konstrukteurs aus Feldern
  9. Pic k und bestellen die Felder, die Sie im Konstruktor ok

Unveränderlichkeit Decorator

Eine andere Idee ist, definieren Sie Ihre Bohne wollen

  • Presse mit Getter und Setter (Sie können die oben genannten Technik verwenden können, sondern umfassen Setter), dann können Sie eine Wrapperklasse dafür erstellen, die nur die Getter enthält.

  • 1

    Was ist eine einfache Schnittstelle nur lesen Sie die Getter cotaining?

    Wenn die Bean-Klasse Ihre eigene ist, implementieren Sie einfach die Schnittstelle und verwenden Sie nur die Schnittstelle nach der Erstellung.

    Wenn Sie keine Kontrolle über die Bean-Klasse haben, können Sie auch eine Getter-Schnittstelle erstellen und sie implementieren, indem Sie einen Proxy für die Getter-Schnittstelle mit einem Aufrufhandler erstellen, der alle Methodenaufrufe an die Bean delegiert.

    Verwandte Themen