2009-07-06 10 views
10

Czy ktoś ma jakieś sugerowane lub ustanowione najlepsze praktyki i konwencje nazewnictwa dla konstruktorów kopii/metod fabrycznych itp. W Javie? W szczególności, powiedzmy, że mam klasę Thing i chcę, aby metoda gdzieś zwróciła nową Thing z tą samą wartością, co przekazana (lub jako instancja, jeśli jest to metoda instancji). Czy masz to jako konstruktora lub statycznej metody fabryki lub metody instancji? Jak nazwałbyś to?Jeśli nie klonujesz w Javie, to co robisz i jak to nazywasz?

Zgodnie z tytułem, chcę uniknąć clone() i Cloneable.

+0

Dlaczego chcesz uniknąć klonowania() i klonowania? –

+0

@Thomas Owens, patrz tutaj: http://www.artima.com/intv/bloch13.html – Yishai

+0

na odpowiedzi, które określają konstruktora kopii jako rozwiązanie: konstruktor kopiowania nie obsługuje poprawnie wszystkich przypadków. Na przykład, gdy nie znasz konkretnej klasy (ale nadal możesz użyć konstruktora kopii wewnątrz metody clone/copy/whateveryoucallit). –

Odpowiedz

3

Nazwałbym to metodą kopiowania lub konstruktorem kopii (w zależności od przypadku). Gdyby to była metoda statyczna, nazwałbym ją fabryką.

Pod względem tego, co zrobić, najbardziej elastyczną i długowieczną opcją jest konstruktor kopii. Dzięki temu podklasy mają możliwość kopiowania samych siebie, podobnie jak rodzic.

2

zrobiłbym konstruktora

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

wtedy, gdy chcesz sklonować go

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

Masz kilka opcji, wdrożyć Cloneable, dodać konstruktor kopiujący, ale mój preferowany sposób jest użycie metody (statycznej lub instancji), która ma nazwę, która jest opisowa dla operacji kopiowania - czy jest to głęboka lub płytka kopia, itp.

15

Efektywne oprogramowanie Java recom naprawia jedno z poniższych kryteriów:

  1. konstruktor kopiujący (jak zauważył innymi):

    Przedmiot publicznych (pozycja Element)

  2. Sposób fabryka kopia:

    public static Item newInstance (pozycja towarowa)

(Nie można również kopiować w przypadku produktów niezmiennych)

Podstawową różnicą jest to, że z # 1 wybierasz rzeczywistą klasę wyniku, a za pomocą # 2 programista może zwrócić podklasę. Semantyka klasy może poprowadzić cię do tego, który z nich jest najlepszy.

0

Użyj immutable data structures. Jedynym powodem, dla którego uważasz, że potrzebujesz clone(), jest mutowanie obiektów w miejscu. Przestań to robić. Zastanów się, jak możesz:

  • Ukończ zajęcia.
  • Uczyń pola w swoich klasach ostatecznymi i prywatnymi.

Na przykład, oto „seter” do niezmiennej obiektu 3D wektora:

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

Więc myślę, że to, co mówię jest ... Używam konstruktorów kopiowania zamiast mutacji, a ja po prostu nadaj im nazwę zgodnie z atrybutem, który chcę zmodyfikować.

0

Inną opcją jest wdrożenie metody kopiowania w źródłowego obiektu, np

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

    void copyCoordsTo(Has3DCoords dest); 
} 

Można by następnie wdrożyć kopiowanie z kawałkiem kodu, takich jak:

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; 
    } 
} 

To może być użyteczne, jeśli:

  • Nie ma sensu klonowanie całego obiektu
  • Istnieje grupa właściwości powiązanych, które są często kopiowane jako jednej jednostki
  • Nie chcesz narażać loc jako własność Thing
  • liczby nieruchomości jest duża (lub istnieje wiele takich grup) tak Konstruktor, który wymagałby ich wszystkich jako parametrów, byłby nieporęczny.
0

To nie jest najładniejszy podejście do kopiowania obiektów, ale po to czasami przydatna, jeśli chcesz wykonać głęboką kopię z Serializable obiektu. Pozwala to uniknąć konieczności pisania konduktorów kopiowania, implementowania klas Cloneable lub pisania klas fabrycznych.

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(); 

Nie zapomnij poradzić sobie z wyjątkami i dobrze zamknąć strumienie.