2009-07-06 11 views
10

¿Alguien tiene alguna recomendación o convenciones de nomenclatura recomendadas o establecidas para constructores de copia/métodos de fábrica, etc. en Java? En particular, digamos que tengo una clase Thing y quiero un método en alguna parte que devuelva un nuevo Thing con el mismo valor que un Thing pasado (o como la instancia si se trata de un método de instancia). ¿Tendría esto como constructor o método de fábrica estático o método de instancia? ¿Como lo llamarias?Si no clona en Java, ¿qué hace y cómo lo llama?

Según el título, quiero evitar clone() y Cloneable.

+0

¿Por qué quieres evitar clone() y clonable? –

+0

@Thomas Owens, consulte aquí: http://www.artima.com/intv/bloch13.html – Yishai

+0

a las respuestas que indican que el constructor de copias es la solución: el constructor de copias no maneja todos los casos de forma adecuada. Por ejemplo, cuando no conoce la clase concreta (pero aún puede usar el constructor de copia dentro de su método clone/copy/whateveryoucallit). –

Respuesta

3

Lo llamaría un método de copia o un constructor de copia (según sea el caso). Si fuera un método estático, entonces lo llamaría fábrica.

En términos de qué hacer, la opción de vida más flexible y larga es un constructor de copia. Esto le da a las subclases la capacidad de copiarse a sí mismas al igual que los padres.

2

lo haría un constructor

... 
public Thing(Thing copyFrom) 
{ 
    attr1 = copyFrom.attr1; 
    attr2 = copyFrom.attr2; 
    //etc... 
} 

entonces cuando se desea clonar

Thing copy = new Thing(copy from me); 
0

Usted tiene algunas opciones, aplicar Cloneable, añadir un constructor de copia, pero mi forma preferida es utilizar un método (estático o de instancia) que tenga un nombre descriptivo de lo que está haciendo la operación de copia, es una copia profunda o superficial, etc.

15

Java recom repara una de las siguientes:

  1. Un constructor de copia (como se ha señalado por otros):

    artículo pública (artículo)

  2. Un método de copia de la fábrica:

    artículo public static nuevaInstancia (Artículo)

(Además, no copia para inmutables)

La principal diferencia es que con # 1 se elige la clase real del resultado, y con # 2, el implementador puede devolver una subclase. La semántica de la clase puede guiarlo hacia cuál es la mejor.

0

Use immutable data structures. La única razón por la que siente que necesita clone() es que está mutando sus objetos en su lugar. Para de hacer eso. Piense en cómo puede:

  • Haga que sus clases sean finales.
  • Haga campos en sus clases finales y privados.

Por ejemplo, he aquí una "incubadora" de un objeto vectorial 3D inmutable:

public Vector3D setX(double x) { 
    return new Vector3D(x, this.y, this.z); 
} 

así que supongo que lo que estoy diciendo es ... Yo uso constructores de copia en lugar de la mutación, y yo solo nómbrelos de acuerdo con el atributo que quiero modificar.

0

Otra opción es poner en práctica el método de copia en el fuente objeto, por ejemplo:

interface Has3DCoords { 
    void setLocation(double x, double y, double z); 

    void copyCoordsTo(Has3DCoords dest); 
} 

A continuación, aplicar la copia con un trozo de código como:

class Thing implements Has3DCoords { 
    private Point3D loc; 
    // ... 

    void setLocation(double x, double y, double z) { 
     loc.setLocation(x, y, z); 
     // or: loc = new Point3D(x, y, z); 
    } 

    void copyCoordsTo(Has3DCoords dest) { 
     loc.copyCoordsTo(dest); 
     // or: dest.setLocation(loc.getX(), loc.getY(), loc.getZ()); 
    } 

    OtherThing createOtherThing() { 
     OtherThing result = new OtherThing(); 
     this.copyCoordsTo(result); 
     return result; 
    } 
} 

Esto puede ser útil si:

  • No tiene sentido clonar todo el objeto
  • Hay un grupo de propiedades relacionadas que a menudo son copiados como una unidad
  • Usted no quiere exponer a loc como una propiedad de Thing
  • El número de propiedades es grande (o hay muchos de estos grupos) por lo un constructor que los requería a todos como parámetros sería difícil de manejar.
0

Este no es el enfoque más agradable a la copia de objetos, pero el siguiente es a veces útil si desea realizar una copia profunda de un objeto Serializable. Esto evita tener que escribir constructores de copia, implementar Clonables o escribir clases de fábrica.

ByteArrayOutputStream bos = new ByteArrayOutputStream(); 
ObjectOutputStream oos = new ObjectOutputStream(bos); 

//Serializes the input object 
oos.writeObject(input); 

ByteArrayInputStream bais = new ByteArrayInputStream(bos.toByteArray()); 
ObjectInputStream ois = new ObjectInputStream(bais); 

//Copy of the input object 
Object output = ois.readObject(); 

No olvide controlar las excepciones y cerrar bien las secuencias.

Cuestiones relacionadas