2009-08-16 20 views
9

Había leído en algún libro de diseño que la clase inmutable mejora la escalabilidad y es una buena práctica escribir clases inmutables siempre que sea posible. Pero creo que la clase tan inmutable aumenta la proliferación de objetos. Entonces, ¿es bueno ir a una clase inmutable o ir a la clase estática (una clase con todos los métodos estáticos) para mejorar la escalabilidad?Clase mutable o inmutable?

Respuesta

5

Las clases inmutables promueven la proliferación de objetos, pero si desea seguridad, los objetos mutables promoverán más proliferación de objetos porque debe devolver copias en lugar del original para evitar que el usuario cambie el objeto que devuelve.

En cuanto al uso de clases con todos los métodos estáticos, esa no es realmente una opción en la mayoría de los casos en los que se podría usar la inmutabilidad. Tome este ejemplo de un 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; } 
} 

¿Cómo exactamente implementaría esto con una clase que contenga solo métodos estáticos?

12

Sin embargo, la principal ventaja de las clases immutable es que puede exponer miembros de datos internos que son inmutables porque la persona que llama no puede modificarlos. Este es un gran problema con, por ejemplo, java.util.Date. Es mutable, por lo que no puede devolverlo directamente desde un método. Esto significa que terminas haciendo todo tipo de defensive copying. Eso aumenta la proliferación de objetos.

El otro gran beneficio es que los objetos inmutables no tienen problemas de synchronization, por definición. Ahí es donde entran los problemas scalability. Escribir el código multithreaded es difícil. Los objetos inmutables son una buena forma de eludir (principalmente) el problema.

En cuanto a las "clases estáticas", en su comentario lo tomo para referirse a las clases con factory methods, que es como se suele describir. Ese es un patrón no relacionado. Tanto las clases mutables como inmutables pueden tener constructores públicos o constructores privados con métodos estáticos de fábrica. Eso no tiene ningún impacto en la (im) mutabilidad de la clase ya que una clase mutable es aquella cuyo estado puede cambiarse después de la creación, mientras que el estado de una clase inmutable no se puede cambiar después de la instanciación.

Los métodos de fábrica estáticos pueden tener otros beneficios. La idea es encapsular la creación de objetos.

+1

Una clase estática es una clase que nunca crea una instancia, pero usa los métodos proporcionados (por ejemplo, Arrays en java). No veo cómo podrían reemplazar las clases inmutables ... – Zed

+0

Probablemente "clase estática" aquí es solo un sinónimo de "clase inmutable". Nada más tiene sentido. – CPerkins

+0

Utilizando "clase estática" quiero decir una clase que contiene todo el método estático con constructor privado (para que el usuario no pueda crear una instancia de la misma clase) sin ningún miembro estático. Perdón por crear confusión. –

1

Como cletus dijo que las clases inmutables simplifican el diseño de clase y el manejo en métodos sincronizados.

También simplifican el manejo en colecciones, incluso en aplicaciones de un solo hilo. Una clase inmutable nunca cambiará, por lo que la clave y el código hash no cambiarán, por lo que no arruinarás tus colecciones.

Pero debe tener en cuenta el ciclo de vida de lo que está modelando y el "peso" del constructor. Si necesita cambiar la cosa, los objetos inmutables se vuelven más complejos de manejar. Tienes que reemplazarlos, en lugar de modificarlos. No es terrible, pero vale la pena considerarlo. Y si el constructor toma un tiempo no trivial, eso también es un factor.

0

La inmutabilidad se usa generalmente para lograr la escalabilidad, ya que la inmutabilidad es uno de los habilitadores cuando se trata de programación concurrente en Java. Entonces, si bien, como usted señala, puede haber más objetos en una solución "inmutable", puede ser un paso necesario para mejorar la concurrencia.

El otro uso igualmente importante de la inmutabilidad es consumir una intención de diseño ; quien hizo una clase inmutable intentó que pusieras el estado mutable en otra parte. Si comienzas a mutar instancias de esa clase, probablemente estás rompiendo la intención original del diseño, y quién sabe cuáles pueden ser las consecuencias.

0

Considere objetos de cuerdas, por ejemplo. Algunos idiomas o bibliotecas de clase proporcionan cadenas mutables, otros no.

Un sistema que utiliza cadenas inmutables puede hacer ciertas optimizaciones que una con cadenas mutables no puede. Por ejemplo, puede asegurarse de que solo haya una copia de una cadena única. Dado que el tamaño del objeto "overhead" es generalmente mucho más pequeño que el tamaño de cualquier cadena no trivial, este es un ahorro de memoria potencialmente masivo. Hay otros posibles ahorros de espacio, como las subcadenas internas.

Además de los posibles ahorros de memoria, los objetos inmutables pueden mejorar la escalabilidad al reducir la contención. Si tiene una gran cantidad de subprocesos que acceden a los mismos datos, los objetos inmutables no requieren procesos de sincronización elaborados para un acceso seguro.

0

Solo una consideración más sobre el tema. El uso de objetos inmutables te permite almacenarlos en la memoria caché y no recrearlos cada vez (es decir, cadenas). Esto ayuda mucho en el rendimiento de tu aplicación.

1

Una cosa a tener en cuenta: si tiene la intención de utilizar instancias de una clase como claves en un HashMap, o si las va a colocar en un HashSet, es más seguro hacerlas inmutables.

HashMap y HashSet cuentan con el hecho de que el código hash para un objeto permanece constante siempre que el objeto esté en el mapa o conjunto. Si utiliza un objeto como clave en un HashMap, o si lo coloca en un HashSet, y luego cambia el estado del objeto para que hashCode() devuelva un valor diferente, entonces está confundiendo HashMap o HashSet y obtendrás cosas extrañas; por ejemplo, cuando itera el mapa o establece que el objeto está ahí, pero cuando intenta obtenerlo, es como si no estuviera allí.

Esto se debe a la forma en que HashMap y HashSet funcionan internamente: organizan objetos por código hash.

This article por el gurú de la concurrencia de Java Brian Goetz ofrece una buena visión general de los pros y los contras de los objetos inmutables.

0

Creo que si quieres compartir el mismo objeto entre diferentes variables, debe ser inmutable.

Por ejemplo:

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

objeto String en Java es inmutable. Ahora ambos A & B apuntan a la misma cadena "abc". Ahora

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

que es la Salida:

abc 

Debido cadena es inmutable, Un simplemente seleccione nuevo "abc123" objeto de cadena en lugar de modificar el objeto de cadena anterior.

+0

-1. A = A + "123" simplemente construirá una nueva cadena (abc123) y la asignará a la variable A. La cadena es inmutable porque no puede convertir la cadena 123 en abc - el objeto String no tiene ninguna opción de asignación. Sin embargo, está perfectamente bien construir un nuevo objeto String entre otros dos. – fwielstra

+0

Bueno, se construyó un nuevo String, y A señalará el NUEVO "abc123". El área de enfoque aquí es un "punto" al objeto NUEVO. No dije que el "abc123" era el resultado de la modificación de "abc" existente ni de "123". – janetsmith