一、原型模式的UML圖
ProtoType: 原型類,聲明一個克隆自己的接口。
ConcreatePrototype: 具體的原型類,是實現克隆自己的操作。
Client: 讓一個原型對象克隆自己,從而產生一個新的對象。對象的屬性完全相同。
二、 原型模式解決克隆羊問題
應用案例:
現在需要將一頭綿羊克隆多個,綿羊要長的一模一樣,請編寫程序實現。
1. 傳統方式實現
package com.exam.prototypecommon;
/**
*author:bingbing
*日期:2020年5月6日
*時間:下午11:15:36
*綿羊
*/
public class Sheep {
private String name;
private int age;
private String color;
public Sheep(String name,int age,String color) {
super();
this.name=name;
this.age=age;
this.color=color;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
@Override
public String toString() {
return "Sheep [name=" + name + ", age=" + age + ", color=" + color + "]";
}
}
測試類:
package com.exam.prototypecommon;
/**
*author:bingbing
*日期:2020年5月6日
*時間:下午11:18:33
*克隆綿羊
*/
public class Test {
public static void main(String[] args) {
Sheep sheep=new Sheep("多利",1,"白色");
Sheep sheep1=new Sheep(sheep.getName(),sheep.getAge(),sheep.getColor());
Sheep sheep2=new Sheep(sheep1.getName(),sheep1.getAge(),sheep1.getColor());
System.out.println("sheep:"+sheep);
System.out.println("sheep1:"+sheep1);
System.out.println("sheep2:"+sheep2);
}
}
注: 最終看的是屬性,因此需要重寫一下toString()方法。
打印結果:
sheep:Sheep [name=多利, age=1, color=白色]
sheep1:Sheep [name=多利, age=1, color=白色]
sheep2:Sheep [name=多利, age=1, color=白色]
2. 使用淺拷貝的方式實現克隆羊問題
淺拷貝介紹
1) 對於數據類型是基本類型的成員變量,將原型的對象屬性,複製一份出來,給新的對象,相當於是值傳遞。
2) 對於數據類型是引用數據類型的成員變量,那麼會進行引用傳遞,比如是成員變量是某個類的對象、數組等,也就是將該成員變量的引用值( 內存地址),複製一份出來給新的對象。實際上新克隆出來的對象的成員變量的引用和原對象的成員變量的引用都指向了同一個實例。在這種情況下,一個對象修改其成員變量,那麼也會影響到另一個對象的該成員變量值,改變的是引用值。
3) 淺拷貝,默認使用的方法是clone()方法來實現。
4) 原對象需要實現Cloneable接口。
3. 使用深拷貝的方式實現克隆羊問題
深拷貝介紹
1) 複製對象的所有基本數據類型的成員變量值
三、使用原型模式需要注意的問題
1. 創建新的對象比較複雜時,使用原型模式,可以一定大大減少代碼量,並且能夠提升效率。
2. 不用重新初始化對象,而是獲取了對象運行時的狀態。
3. 如果原對象發生變化,那麼其它克隆的對象也會發生變化,無需修改代碼。
4. 在使用深拷貝時,可能需要寫很多複雜的代碼。
5. 需要爲每個類配備一個克隆方法,對已有的類進行改造時,需要修改其源代碼,那麼違背了OCP原則。