2011-01-04 14 views
5

Al crear clases para "objetos inmutables" inmutables, lo que significa que el estado de las instancias no se puede cambiar; todos los campos asignados en el constructor) en Java (e idiomas similares), a veces es útil permitir la creación de instancias modificadas. Es decir, usar una instancia como base y crear una nueva instancia que difiera en un solo valor de propiedad; otros valores que provienen de la instancia base. Para dar un ejemplo sencillo, se podría tener clase como:Cómo llamar a los métodos de fábrica (java) utilizados con objetos inmutables

public class Circle { 
    final double x, y; // location 
    final double radius; 

    public Circle(double x, double y, double r) { 
    this.x = x; 
    this.y = y; 
    this.r = r; 
    } 

    // method for creating a new instance, moved in x-axis by specified amount 
    public Circle withOffset(double deltaX) { 
    return new Circle(x+deltaX, y, radius); 
    } 
} 

Por lo tanto: lo que debe ser llamado método de "withOffset"? (nota: NO cuál debería ser su nombre, pero a qué se llama esta clase de métodos). Técnicamente es una especie de método de fábrica, pero de alguna manera eso no me parece correcto, ya que a menudo las fábricas solo tienen propiedades básicas (y son métodos estáticos, o no son miembros del tipo de resultado sino de fábrica).

Así que supongo que debería haber un término mejor para tales métodos. Dado que estos métodos se pueden usar para implementar "fluent interface", ¿podrían ser "métodos de fábrica fluidos"? ¿Mejores sugerencias?

EDITAR: como se sugiere en una de las respuestas, java.math.BigDecimal es un buen ejemplo con sus métodos 'agregar', 'restar' (etc.).

también: me di cuenta de que hay this question (por Jon Skeet nada menos) que es una especie de relacionado (aunque pide nombre acerca específica para el método)

EDITAR, MAYO-2014: Mi favorito actual es mutant factory, Fwiw .

+0

Lo llamaría un método mal llamado. – Falmarri

+0

"mover" y "delta" implican mutabilidad de las propiedades de una instancia existente ... – BoltClock

+0

Lea la pregunta real: NO pregunté cómo nombrar los métodos, sino cómo denominarlos. Pero solo para evitar que otros tropiecen con líneas laterales, editaré el código un poco. – StaxMan

Respuesta

3

llamo esos tipos de métodos "métodos de copia".

Mientras que el método clone() crea una copia exacta, un método de copia hace una copia de una instancia, generalmente con una variación implícita o explícita. Por ejemplo, String#toUpperCase() sería un método de copia de la clase de cadena inmutable; copia una instancia con una variación: guarda todas las letras.

Considero que el método withOffset() en su ejemplo es un método de copia similar.

No conozco ninguna referencia que documente el término "método de copia". Estoy tomando prestado el término "copia" de su uso en C++: constructores de copia y la directriz de denominación "copia" de los Estándares de codificación Taligent (more info).


En cuanto al término "métodos de fábrica con fluidez", no sé por qué "fluidez" haría una diferencia, ya que una "interfaz fluida" es sólo un estilo de API (separada de la Builder). Si el término "método de fábrica" ​​no se aplica aquí, no veo cómo llamarlo un "método de fábrica fluido" hace que se aplique mejor.

+0

La parte fluida fue solo una sugerencia, basada en el hecho de que tales métodos a menudo se usan para respaldar el estilo fluido. Sin embargo, no es lo mismo que el estilo fluido no exige (ni necesariamente promueve) la inmutabilidad. El "método de copia" suena razonable, veamos si alguien tiene incluso mejores sugerencias. (De hecho, estaba a punto de mencionar "copy constructor" como referencia en cuestión, pero decidí no intentar eliminar posibles confusiones) – StaxMan

1

Esto realmente no parece un método de fábrica. La firma sola solo me dice que puedo encadenarla en diferentes llamadas, pero no que se suponga que cree una nueva instancia: Veo este caso de uso más como un StringBuilder que permite anexar ("a"). "segundo"). Podría, por supuesto, devolver un nuevo StringBuilder cada vez (como lo hace su Círculo).

Así que no es por diseño una fábrica. (Piense en extraer la interfaz y escribir JavaDoc para ese método: "uno debe devolver una nueva instancia, ya que soy inmutable", ¿por qué?). El hecho de que su clase sea inmutable es solo un detalle de implementación.

EDITAR: Perahs, un ejemplo mejor sería BigInteger, ya que también es inmutable. Junto con multiplicar (BigInteger), que proporciona un método paquete-privada:

BigInteger multiply(long v) 

que devuelve una nueva instancia y se asemeja a su caso muy bien. Eso es simplemente una operación que resulta devolver un resultado del mismo tipo que el objeto inicial; no es una fábrica y no creo que este tipo de operación realmente merezca su propio nombre.

+0

Estoy de acuerdo en que no es un método de fábrica , y es por eso que esperaba encontrar un mejor término. BigInteger es un buen ejemplo. Pero más allá de esto, nótese que la inmutabilidad es un aspecto MUY importante aquí; y definitivamente no (solo) un detalle de implementación: el objeto completo debe ser inmutable, no solo operaciones con este método. ¿Tal vez no esté familiarizado con el estilo o los beneficios de objetos inmutables? Ayuda tremendamente con multi-threading y con estructuras de datos concurrentes. Con StringBuilder, la devolución de la instancia es solo una conveniencia que permite el encadenamiento. – StaxMan

+0

Nunca dije que el método es inmutable, la inmutabilidad se refiere a los objetos de tu clase Circle en mi publicación. Dije "Implementar detalles" porque intento simplemente mirar ese método para clasificarlo e ignorar la implementación real. Todo lo que digo es que si fuera un método abstracto (declarado en una interfaz), es poco probable que requiera que todas las implementaciones se comporten como esta. Por lo tanto, creo que este comportamiento no es esencial para este método. –

+0

Creo que encontré un mejor ejemplo: String.concat() - aunque eso no proviene de la interfaz CharSequence. El javadoc dice: "Si la longitud de la cadena del argumento es 0, entonces este objeto String es devuelto". Podría hacer lo mismo si el desplazamiento X es 0, por lo que un objeto nuevo ni siquiera es un requisito. –

3

Hrm ... crea versiones mutadas del objeto ... tal vez deberíamos llamarlo una fábrica de mutantes? :-)

+0

Jeje, me gusta eso. :) – StaxMan

Cuestiones relacionadas