設計模式--創建型--原型模式
- 原型模式
- 概述
- 結構
- 實現
- 結果
- 案例
- 代碼
- 結果
- 使用場景
- 擴展(深\淺克隆)
- 淺克隆演示:
- 結果:
- 使用深克隆(利用對象流)
- 結果
原型模式
概述
用一個已經創建的實例作為原型,通過復制該原型對象來創建一個和原型對象相同的新對象。
結構
原型模式包含如下角色
- 抽象原型類:規定了具體原型對象必須實現的clone()方法
- 具體原型類:實現抽象原型的clone()方法,它是可被復制的對象。
- 訪問類:使用具體原型類中的clone()方法來復制新的對象。
實現
原型模式的克隆分為淺克隆和深克隆。
- 淺克隆:創建一個新對象,新對象的屬性和原來對象完全相同,對于非基本類型屬性,仍指向原有屬性所指向的對象的內存地址
- 深克隆:創建一個新對象,屬性中引用的其他對象也會被克隆,不在指向原有對象地址。
Java中的Object類中提供了clone()方法來實現淺克隆。
/*** 具體的原型類實現Cloneable接口 這里用Cloneable接口來當做抽象原型類*/
public class RealizeType implements Cloneable{public RealizeType(){System.out.println("使用構造器創建具體的原型對象");};/*** 重寫clone()方法* @return RealizeType*/@Overridepublic RealizeType clone() throws CloneNotSupportedException{System.out.println("clone具體原型對象成功");return (RealizeType) super.clone();}
}
public class Test01 {public static void main(String[] args) throws CloneNotSupportedException {// 創建一個原型對象RealizeType realizeType = new RealizeType();// 調用RealizeType中的clone方法進行對象的克隆RealizeType clone = realizeType.clone();System.out.println("原型對象和克隆對象是否是同一個對象?"+ (clone == realizeType));}
}
結果
案例
用原型模式生成"三好學生"獎狀
獎狀除了獲獎人信息不同,其他都相同,可以使用原型模式復制多個“三好學生獎狀”,然后修改學生信息即可
代碼
public class Citation implements Cloneable{private String name;public String getName(){return name;}public void setName(String name){this.name = name;}@Overridepublic Citation clone() throws CloneNotSupportedException{return (Citation) super.clone();}public void info(){System.out.println(name + "同學的獎狀");}
}
public class Test01 {public static void main(String[] args) throws CloneNotSupportedException {// 創建獎狀原型Citation citation = new Citation();citation.setName("張三");Citation clone = citation.clone();clone.setName("李四");citation.info();clone.info();}
}
結果
- 這里雖然是淺拷貝但是name屬性沒有改變,是因為name是String類型,如果是引用類型并且還是淺拷貝,那么原型對象中的name是改變的,下面是深、淺克隆演示。
使用場景
- 對象的創建非常復雜,可以使用原型模式快捷的創建對象
- 性能和安全的要求比較高
擴展(深\淺克隆)
這里將上面的name屬性放到一個student對象中,而Citation類中的Student屬性就是引用屬性
淺克隆演示:
public class Citation implements Cloneable{private Student stu;public Student getStu(){return stu;}public void setStu(Student stu){this.stu = stu;}@Overridepublic Citation clone() throws CloneNotSupportedException{return (Citation) super.clone();}public void info(){System.out.println(stu.getName() + "同學的獎狀");}
}
public class Student {private String name;public String getName(){return name;}public void setName(String name){this.name = name;}
}
public class Test01 {public static void main(String[] args) throws CloneNotSupportedException {// 創建獎狀原型Citation citation = new Citation();// 創建學生對象Student student = new Student();student.setName("張三");citation.setStu(student);citation.info();// 克隆Citation clone = citation.clone();// 重新設置學生姓名clone.getStu().setName("李四");citation.info();clone.info();}
}
結果:
說明:原型對象和克隆出來的對象中的student對象是同一個對象,修改其中一個,另一個的值也會改變。
這就是淺克隆的效果,對具體原型類中的引用數據類型進行引用的復制。
使用深克隆(利用對象流)
克隆時先將原型對象寫入文件中,再讀取。
public class Citation implements Cloneable, Serializable {private Student stu;public Student getStu(){return stu;}public void setStu(Student stu){this.stu = stu;}@Overridepublic Citation clone() throws CloneNotSupportedException{return (Citation) super.clone();}public void info(){System.out.println(stu.getName() + "同學的獎狀");}
}
public class Student implements Serializable {private String name;public String getName(){return name;}public void setName(String name){this.name = name;}
}
public class Test02 {public static void main(String[] args) throws Exception {// 創建獎狀原型Citation citation = new Citation();// 創建學生對象Student student = new Student();student.setName("張三");citation.setStu(student);citation.info();// 創建對象輸出流對象ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("e:/a.txt"));// 寫對象oos.writeObject(citation);// 釋放oos.close();// 創建對象輸入流對象ObjectInputStream ois = new ObjectInputStream(new FileInputStream("e:/a.txt"));// 讀取對象Citation citation1 = (Citation) ois.readObject();ois.close();citation1.getStu().setName("李四");citation.info();citation1.info();}
}