2009-08-16 28 views
9

Ich hatte in einem Designbuch gelesen, dass die unveränderliche Klasse die Skalierbarkeit und die gute Praxis verbessert, wo immer möglich unveränderliche Klassen zu schreiben. Aber ich denke, dass so unveränderliche Klasse die Proliferation von Objekten erhöht. Ist es also gut, eine unveränderliche Klasse zu verwenden oder lieber eine statische Klasse (Klasse A mit allen Methoden statisch) zu verwenden, um die Skalierbarkeit zu verbessern?Veränderbare oder unveränderliche Klasse?

Antwort

5

unveränderliche Klassen tun Objekt Proliferation fördern, aber wenn Sie Sicherheit wollen, veränderbare Objekte mehr Objekt Proliferation fördern, weil Sie Kopien zurückkommen müssen, anstatt das Original von Ändern Sie das Objekt, um den Benutzer zu verhindern zurückzukehren.

Wenn Sie Klassen mit allen statischen Methoden verwenden, ist das in den meisten Fällen, in denen die Unveränderlichkeit verwendet werden könnte, nicht wirklich eine Option. Nehmen Sie dieses Beispiel aus einem RPG:

public class Weapon 
{ 
    final private int attackBonus; 
    final private int accuracyBonus; 
    final private int range; 

    public Weapon(int attackBonus, int accuracyBonus, int range) 
    { 
     this.attackBonus = attackBonus; 
     this.accuracyBonus = accuracyBonus; 
     this.range = range; 
    } 

    public int getAttackBonus() { return this.attackBonus; } 
    public int getAccuracyBonus() { return this.accuracyBonus; } 
    public int getRange() { return this.range; } 
} 

Wie genau würden Sie dies mit einer Klasse implementieren, die nur statische Methoden enthält?

12

Der Hauptvorteil von Klassen immutable ist jedoch, dass Sie interne Datenelemente verfügbar machen können, die unveränderlich sind, da der Aufrufer sie nicht ändern kann. Dies ist ein großes Problem mit, sagen wir java.util.Date. Es ist änderbar, so dass Sie es nicht direkt von einer Methode zurückgeben können. Das bedeutet, dass Sie am Ende alle Arten von defensive copying tun. Das erhöht die Proliferation von Objekten.

Der andere große Vorteil ist, dass unveränderliche Objekte per Definition keine synchronization Probleme haben. Das ist, wo die scalability Probleme kommen. Schreiben multithreaded Code ist schwer. Unveränderliche Objekte sind eine gute Möglichkeit, das Problem (meistens) zu umgehen.

Was "statische Klassen" angeht, nehme ich anhand Ihres Kommentars Klassen mit factory methods, wie es normalerweise beschrieben wird. Das ist ein nicht verwandtes Muster. Sowohl veränderbare als auch unveränderbare Klassen können entweder öffentliche Konstruktoren oder private Konstruktoren mit statischen Factory-Methoden haben. Dies hat keinen Einfluss auf die (Un-) Veränderlichkeit der Klasse, da eine veränderbare Klasse eine ist, deren Zustand nach der Erzeugung geändert werden kann, während der Zustand einer unveränderlichen Klasse nach der Instanziierung nicht geändert werden kann.

Statische Fabrikmethoden können jedoch andere Vorteile haben. Die Idee besteht darin, die Objekt-Erstellung zu kapseln.

+1

Eine statische Klasse ist eine Klasse, die Sie niemals instanziieren, sondern ihre bereitgestellten Methoden verwenden (z. B. Arrays in Java). Ich sehe jedoch nicht, wie sie unveränderliche Klassen ersetzen könnten ... – Zed

+0

Wahrscheinlich ist "statische Klasse" hier nur ein Synonym für "unveränderliche Klasse". Nichts anderes macht Sinn. – CPerkins

+0

Mit "Statische Klasse" möchte ich eine Klasse sagen, die die gesamte statische Methode mit privatem Konstruktor enthält (So kann der Benutzer keine Instanz der gleichen Klasse erstellen) ohne ein statisches Member. Entschuldigung für Verwirrung. –

1

Wie Cletus sagte, unveränderliche Klassen vereinfachen Klassenentwurf und Handhabung in synchronisierten Methoden.

Sie vereinfachen auch die Handhabung in Sammlungen, auch in Singlethread-Anwendungen. Eine unveränderliche Klasse wird sich niemals ändern, also werden sich der Schlüssel und der Hashcode nicht ändern, so dass Sie Ihre Sammlungen nicht vermasseln.

Aber Sie sollten den Lebenszyklus der Sache, die Sie modellieren und das "Gewicht" des Konstruktors berücksichtigen. Wenn Sie die Sache ändern müssen, werden unveränderliche Objekte komplexer. Sie müssen sie ersetzen, anstatt sie zu ändern. Nicht schrecklich, aber eine Überlegung wert. Und wenn der Konstrukteur nichttriviale Zeit braucht, ist das auch ein Faktor.

0

Unveränderlichkeit wird im Allgemeinen verwendet, um Skalierbarkeit zu erreichen, da Unveränderbarkeit einer der Gründe ist, wenn es um gleichzeitige Programmierung in Java geht. Während Sie darauf hinweisen, dass es möglicherweise mehr Objekte in einer "unveränderlichen" Lösung gibt, kann dies ein notwendiger Schritt zur Verbesserung der Parallelität sein.

Die andere, ebenso wichtige Verwendung und Unveränderlichkeit ist ein Design Absicht; Wer immer eine unveränderliche Klasse bildete, wollte, dass man anderswo einen veränderlichen Zustand einführte. Wenn Sie beginnen, Instanzen dieser Klasse mutieren zu lassen, brechen Sie wahrscheinlich die ursprüngliche Absicht des Entwurfs - und wer weiß, was die Konsequenzen sein können.

0

Betrachten Sie String-Objekte als Beispiel. Einige Sprachen oder Klassenbibliotheken bieten veränderbare Zeichenfolgen, andere nicht.

Ein System, das unveränderliche Strings verwendet, kann bestimmte Optimierungen vornehmen, die mit veränderbaren Strings nicht möglich sind. Beispielsweise können Sie sicherstellen, dass nur eine Kopie einer eindeutigen Zeichenfolge vorhanden ist. Da die Größe des Objekts "Overhead" im Allgemeinen viel kleiner ist als die Größe einer nicht-trivialen Zeichenfolge, ist dies eine potentiell massive Speichereinsparung. Es gibt weitere potenzielle Platzeinsparungen, wie zum Beispiel das Einlernen von Teilstrings.

Neben den potenziellen Speicherersparnissen können unveränderliche Objekte die Skalierbarkeit verbessern, indem sie Konflikte reduzieren. Wenn eine große Anzahl von Threads auf dieselben Daten zugreifen, benötigen unveränderliche Objekte keine komplizierten Synchronisationsprozesse für den sicheren Zugriff.

0

Nur eine weitere Überlegung zu diesem Thema. Wenn Sie immutable object verwenden, können Sie sie zwischenspeichern und nicht jedes Mal neu erstellen (zB Strings). Dies hilft sehr bei der Performance Ihrer Anwendung.

1

Eine Sache zu beachten: Wenn Sie Instanzen einer Klasse als Schlüssel in einer HashMap verwenden möchten oder wenn Sie sie in ein HashSet einfügen möchten, ist es sicherer, sie unveränderlich zu machen.

HashMap und HashSet zählen darauf, dass der Hash-Code für ein Objekt konstant bleibt, solange sich das Objekt in der Map oder im Set befindet. Wenn Sie ein Objekt als Schlüssel in einer HashMap verwenden oder wenn Sie es in ein HashSet einfügen und dann den Status des Objekts ändern, sodass hashCode() einen anderen Wert zurückgibt, dann verwirren Sie die HashMap oder HashSet und Du wirst seltsame Dinge bekommen; Wenn Sie zum Beispiel die Karte iterieren oder das Objekt festlegen, ist es dort, aber wenn Sie versuchen, es zu bekommen, ist es, als ob es nicht da wäre.

Dies liegt daran, wie HashMap und HashSet intern arbeiten - sie organisieren Objekte durch Hash-Code.

This article von Java Concurrency Guru Brian Goetz gibt einen guten Überblick über die Vor- und Nachteile von unveränderlichen Objekten.

0

Ich denke, wenn Sie das gleiche Objekt unter verschiedenen Variablen teilen möchten, muss es unveränderlich sein.

Zum Beispiel:

String A = "abc"; 
String B = "abc"; 

String-Objekt in Java ist unveränderlich. Jetzt zeigen beide A & B auf die gleiche "abc" Zeichenkette. Jetzt

A = A + "123"; 
System.out.println(B); 

es ausgeben soll:

abc 

Da String unveränderlich ist, A wird einfach auf neue Punkt "abc123" String-Objekt anstelle der vorherigen String-Objekt zu ändern.

+0

-1. A = A + "123" erstellt einfach eine neue Zeichenfolge (abc123) und weist sie der Variablen A zu. String ist unveränderlich, da Sie die 123-Zeichenfolge nicht in abc umwandeln können - das String-Objekt verfügt nicht über Zuweisungsoptionen. Es ist völlig in Ordnung, ein neues String-Objekt aus zwei anderen zu erstellen. – fwielstra

+0

Nun, ein neuer String wurde gebaut, und A wird den neuen "abc123" zeigen. Der Fokusbereich ist hier ein "Punkt" zu einem NEUEN Objekt. Ich habe nicht gesagt, dass "abc123" das Ergebnis der Modifikation von "abc" oder "123" war. – janetsmith

Verwandte Themen