概念
原型模式是一個創建型的模式。用原型實例指定創建對象的種類,並且通過拷貝這些原型,創建新的對象。原型模式多用於創建複雜的或者構造耗時的實例,因爲這種情況下,複製一個已經存在的實例可使程序運行更高效。原型模式是用於創建重複的對象,同時又能保證性能。,原型模式提供了一種創建對象的最佳方式。這種模式是實現了一個原型接口,該接口用於創建當前對象的克隆。當直接創建對象的代價比較大時,則採用這種模式。
工作原理
通過將一個原型對象傳給那個要發動創建的對象,這個要發動創建的對象通過請求原型對象拷貝它們自己來實現創建,即 對象.clone()
傳統方式克隆和原型模式比較
傳統方式:
public class Person {
//名字
private String name;
//年齡
private int age;
//膚色
private String color;
//性別
private String sex;
public Person(String name, int age, String color, String sex) {
super();
this.name = name;
this.age = age;
this.color = color;
this.sex = sex;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
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 "Person{" +
"name='" + name + '\'' +
", age=" + age +
", color='" + color + '\'' +
", sex=" + sex +
'}';
}
}
public class PrototypeDemo {
public static void main(String[] args) {
Person person = new Person("張三", 20, "黃色","男");
Person person2 = new Person(person.getName(), person.getAge(), person.getColor(), person.getSex());
Person person3 = new Person(person.getName(), person.getAge(), person.getColor(), person.getSex());
System.out.println(person.toString());
System.out.println(person2.toString());
System.out.println(person3.toString());
}
}
輸出
Person{name='張三', age=12, color='黃色', sex=男}
Person{name='張三', age=12, color='黃色', sex=男}
Person{name='張三', age=12, color='黃色', sex=男}
優點:
好理解,簡單易操作
缺點:
1.在創建新的對象時,總是需要重新獲取原始對象的屬性,如果創建的對象比較複雜時,效率較低。
2.總是需要重新初始化對象,而不是動態地獲得對象運行時的狀態,不夠靈活。
簡單原型模式方式:
public class Person2 implements Cloneable {
//名字
private String name;
//年齡
private int age;
//膚色
private String color;
//性別
private String sex;
public Person2(String name, int age, String color, String sex) {
super();
this.name = name;
this.age = age;
this.color = color;
this.sex = sex;
}
/**
* 克隆該實例,使用默認的clone方法來完成
*/
@Override
protected Person2 clone() {
Person2 person2 = null;
try {
person2 = (Person2)super.clone();
} catch (Exception e) {
e.printStackTrace();
}
return person2;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
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 "Person2{" +
"name='" + name + '\'' +
", age=" + age +
", color='" + color + '\'' +
", sex=" + sex +
'}';
}
}
public class PrototypeDemo2 {
public static void main(String[] args) {
Person2 person = new Person2("張三", 20, "黃色","男");
Person2 person2 = person.clone();
Person2 person3 = person.clone();
System.out.println(person.toString());
System.out.println(person2.toString());
System.out.println(person3.toString());
}
}
輸出:
Person2{name='張三', age=20, color='黃色', sex=男}
Person2{name='張三', age=20, color='黃色', sex=男}
Person2{name='張三', age=20, color='黃色', sex=男}
除了簡單原型模式,對象的拷貝還有深拷貝,淺拷貝:具體看文章:
深拷貝和淺拷貝詳解以及實例
優點:
1.當創建新的對象實例較爲複雜時,使用原型模式可以簡化對象的創建過程,通過複製一個已有實例可以提高新實例的創建效率。
2.擴展性較好,由於在原型模式中提供了抽象原型類,在客戶端可以針對抽象原型類進行編程,而將具體原型類寫在配置文件中,增加或減少產品類對原有系統都沒有任何影響。
3.原型模式提供了簡化的創建結構,工廠方法模式常常需要有一個與產品類等級結構相同的工廠等級結構,而原型模式就不需要這樣,原型模式中產品的複製是通過封裝在原型類中的克隆方法實現的,無須專門的工廠類來創建產品。
4.可以使用深克隆的方式保存對象的狀態,使用原型模式將對象複製一份並將其狀態保存起來,以便在需要的時候使用(如恢復到某一歷史狀態),可輔助實現撤銷操作。
5.性能提高。
6.逃避構造函數的約束。
缺點:
1.配備克隆方法需要對類的功能進行通盤考慮,這對於全新的類不是很難,但對於已有的類不一定很容易,特別當一個類引用不支持串行化的間接對象,或者引用含有循環結構的時候。
2.必須實現 Cloneable 接口。
如果大家對java架構相關感興趣,可以關注下面公衆號,會持續更新java基礎面試題, netty, spring boot,spring cloud等系列文章,一系列乾貨隨時送達, 超神之路從此展開, BTAJ不再是夢想!