設計模式之原型模式

2021-08-04 18:49:38 字數 3396 閱讀 4880

原型模式用於複製物件,需要實現cloneable介面,重寫object類中的clone()。

對於乙個物件x來說,複製一般是要達到以下效果,雖然不是強制的:

1. x.clone != x 為true

2. x.clone.getclass() == x.getclass() 為true

3. x.clone.equals(x) 為true

通常重寫clone()是重寫成呼叫super.clone(),如果乙個類及其所有父類都有符合這個標準,則x.clone.getclass() == x.getclass()是成立的。

如果要實現equals()為true,則要重寫equals()自行實現邏輯比較。

如果乙個類只包含基本資料型別或者對於不可變物件的引用,則只需直接返回super.clone()的物件即可。

但是如果這個類包含了可變物件,如果只是單純複製一層,則只會複製可變物件的引用,實際指向的還是同乙個可變物件。所以需要對可變物件進行複製,然後獲取到複製後物件的引用,才能實現深層複製。

既然呼叫了super.clone(),則需要把object類的clone()所進行的操作弄清楚。object.clone()首先會檢查這個類是否實現了cloneable介面,如果沒有就會丟擲clonenotsupportedexception。

所有的陣列預設都實現了cloneable介面,對於乙個任意型別陣列t,它的clone方法返回就是t。

檢查實現了cloneable介面之後,這個方法會建立這個類的新例項,然後以所複製物件的對應欄位值來初始化新例項,就好像是正常賦值一樣。注意這裡並沒有把字段本身也複製了,即如果是物件的話只複製引用,所以object.clone()預設只是淺複製。

object類本身並沒有實現cloneable介面,本身clone()也是protected。如果子類沒有實現cloneable介面,就重寫clone()許可權並呼叫,會丟擲異常。

目標類:

public

class

student

implements

cloneable

@override

public student clone() catch (clonenotsupportedexception e)

return

null;

}@override

public

boolean

equals(object obj)

if (!(obj instanceof student))

student counterpart = (student) obj;

return name.equals(counterpart.name) && age == counterpart.age;

}@override

public string tostring()

public

intgetage()

public

void

setage(int age)

}

測試類:

public

class test

}

輸出:

true

true

name = tim, age = 10

name = tim, age = 26

如果所複製物件包含可變物件引用,則淺複製只能複製其引用,如果所引用的物件發生改變,則複製得到物件的對應可變物件也會發生改變,指向的是同一片記憶體,這種情況下就需要深複製。

深複製的實現是通過可變物件也實現cloneable介面,重寫clone()。然後得到外層複製物件後,對其可變物件進行再次複製。

下面給student新增乙個subject物件欄位以說明過程:

目標類:

public

class

student

implements

cloneable

@override

public student clone() catch (clonenotsupportedexception e)

return

null;

}@override

public

boolean

equals(object obj)

if (!(obj instanceof student))

student counterpart = (student) obj;

return name.equals(counterpart.name) && age == counterpart.age && subject.equals(counterpart.subject);

}@override

public string tostring()

public

intgetage()

public

void

setage(int age)

public subject getsubject()

public

void

setsubject(subject subject)

}

目標類所包含的可變欄位類:

public

class

subject

implements

cloneable

@override

public subject clone() catch (clonenotsupportedexception e)

return

null;

}@override

public

boolean

equals(object obj)

if(!(obj instanceof subject))

subject counterpart = (subject)obj;

return

this.name.equals(counterpart.name);

}@override

public string tostring()

public string getname()

public

void

setname(string name)

}

測試類:

public

class test

}

輸出:

true

true

name = tim, age = 10, subject = english

name = tim, age = 26, subject = math

設計模式之原型模式

原型模式其實就是從乙個物件再建立乙個可定製的物件,而且不需要知道建立的細節。具體就是說通過複製或者轉殖乙個原型物件產生新的物件 轉殖物件 分為兩種 深複製或者淺複製,這兩種的主要區別是 在原型中如果有物件的引用,淺複製是將引用複製過來了,也就是淺複製和原型中的物件的引用相同,而深複製是將轉殖物件中引...

設計模式之原型模式

include include 此練習為原型模式方法的練習 原型模式揭示了在同一原型上可以通過複製使得 只需要例項化一次,再通過相應的類函式操作可以得到 同一原型下的不同的版本物件 此練習將考慮在實際開發中 比如 工作經歷也是作為乙個類被含在簡歷類中的情況 這情況將涉及到類的引用和深 淺複製 原型基...

設計模式之原型模式

原型模式的思想就是將乙個物件作為原型,對其進行複製 轉殖,產生乙個和原物件類似的新物件 複製過程可分為淺複製和深複製。淺複製是指直接呼叫父類 即object類 的clone方法 super.clone 該方法是本地 native 方法,呼叫該方法clone出來的新物件,基本資料型別的屬性變數是新建立...