一、原型模式
1. 概述
用一個(gè)已經(jīng)創(chuàng)建的實(shí)例作為原型,通過(guò)復(fù)制該原型對(duì)象來(lái)創(chuàng)建一個(gè)和原型對(duì)象相同的新對(duì)象。
2. 結(jié)構(gòu)
原型模式包含如下角色:
- 抽象原型類(lèi):規(guī)定了具體原型對(duì)象必須實(shí)現(xiàn)的 clone() 方法。
- 具體原型類(lèi):實(shí)現(xiàn)抽象原型類(lèi)的 clone() 方法,它是可被復(fù)制的對(duì)象。
- 訪問(wèn)類(lèi):使用具體原型類(lèi)中的 clone() 方法來(lái)復(fù)制新的對(duì)象。
接口類(lèi)圖如下:
3. 實(shí)現(xiàn)
原型模式的克隆分為淺克隆和深克隆。
淺克?。簞?chuàng)建一個(gè)新對(duì)象,新對(duì)象的屬性和原來(lái)對(duì)象完全相同,對(duì)于非基本類(lèi)型屬性,仍指向原有屬性所指向的對(duì)象的內(nèi)存地址。
深克?。簞?chuàng)建一個(gè)新對(duì)象,屬性中引用的其他對(duì)象也會(huì)被克隆,不再指向原有對(duì)象地址。
Java中的Object類(lèi)中提供了
clone()
方法來(lái)實(shí)現(xiàn)淺克隆。 Cloneable 接口是上面的類(lèi)圖中的抽象原型類(lèi),而實(shí)現(xiàn)了Cloneable接口的子實(shí)現(xiàn)類(lèi)就是具體的原型類(lèi)。
Realizetype(具體的原型類(lèi)):
public class Realizetype implements Cloneable {
public Realizetype() {
System.out.println("具體的原型對(duì)象創(chuàng)建完成!");
}
@Override
public Realizetype clone() throws CloneNotSupportedException {
System.out.println("具體原型復(fù)制成功!");
return (Realizetype) super.clone();
}
}
PrototypeTest(測(cè)試訪問(wèn)類(lèi)):
public class PrototypeTest {
public static void main(String[] args) throws CloneNotSupportedException {
//創(chuàng)建一個(gè)原型類(lèi)對(duì)象
Realizetype realizetype = new Realizetype();
//調(diào)用Realizetype類(lèi)中的clone方法進(jìn)行對(duì)象的克隆
Realizetype clone = realizetype.clone();
System.out.println("原型對(duì)象和克隆出來(lái)的是否是同一個(gè)對(duì)象?" + (realizetype == clone));
}
}
運(yùn)行結(jié)果為:
4. 案例
用原型模式生成“三好學(xué)生”獎(jiǎng)狀
同一學(xué)校的“三好學(xué)生”獎(jiǎng)狀除了獲獎(jiǎng)人姓名不同,其他都相同,可以使用原型模式復(fù)制多個(gè)“三好學(xué)生”獎(jiǎng)狀出來(lái),然后在修改獎(jiǎng)狀上的名字即可。
獎(jiǎng)狀類(lèi):
public class Citation implements Cloneable {
private String name;
public void setName(String name) {
this.name = name;
}
public String getName() {
return (this.name);
}
public void show() {
System.out.println(name + "同學(xué):在2020學(xué)年第一學(xué)期中表現(xiàn)優(yōu)秀,被評(píng)為三好學(xué)生。特發(fā)此狀!");
}
@Override
public Citation clone() throws CloneNotSupportedException {
return (Citation) super.clone();
}
}
測(cè)試訪問(wèn)類(lèi):
public class CitationTest {
public static void main(String[] args) throws CloneNotSupportedException {
Citation c1 = new Citation();
c1.setName("張三");
//復(fù)制獎(jiǎng)狀
Citation c2 = c1.clone();
//將獎(jiǎng)狀的名字修改李四
c2.setName("李四");
c1.show();
c2.show();
}
}
運(yùn)行結(jié)果為:
1.5 使用場(chǎng)景
- 對(duì)象的創(chuàng)建非常復(fù)雜,可以使用原型模式快捷的創(chuàng)建對(duì)象。
- 性能和安全要求比較高。
1.6 擴(kuò)展(深克隆)
將上面的“三好學(xué)生”獎(jiǎng)狀的案例中Citation類(lèi)的name屬性修改為Student類(lèi)型的屬性。
獎(jiǎng)狀類(lèi):
public class Citation implements Cloneable {
private Student stu;
public Student getStu() {
return stu;
}
public void setStu(Student stu) {
this.stu = stu;
}
void show() {
System.out.println(stu.getName() + "同學(xué):在2020學(xué)年第一學(xué)期中表現(xiàn)優(yōu)秀,被評(píng)為三好學(xué)生。特發(fā)此狀!");
}
@Override
public Citation clone() throws CloneNotSupportedException {
return (Citation) super.clone();
}
}
學(xué)生類(lèi):
public class Student {
private String name;
private String address;
public Student(String name, String address) {
this.name = name;
this.address = address;
}
public Student() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
測(cè)試類(lèi):
public class CitationTest {
public static void main(String[] args) throws CloneNotSupportedException {
Citation c1 = new Citation();
Student stu = new Student("張三", "西安");
c1.setStu(stu);
//復(fù)制獎(jiǎng)狀
Citation c2 = c1.clone();
//獲取c2獎(jiǎng)狀所屬學(xué)生對(duì)象
Student stu1 = c2.getStu();
stu1.setName("李四");
//判斷stu對(duì)象和stu1對(duì)象是否是同一個(gè)對(duì)象
System.out.println("stu和stu1是同一個(gè)對(duì)象?" + (stu == stu1));
c1.show();
c2.show();
}
}
運(yùn)行結(jié)果為:
說(shuō)明:
? stu對(duì)象和stu1對(duì)象是同一個(gè)對(duì)象,就會(huì)產(chǎn)生將stu1對(duì)象中name屬性值改為“李四”,兩個(gè)Citation(獎(jiǎng)狀)對(duì)象中顯示的都是李四。這就是淺克隆的效果,對(duì)具體原型類(lèi)(Citation)中的引用類(lèi)型的屬性進(jìn)行引用的復(fù)制。這種情況需要使用深克隆,而進(jìn)行深克隆需要使用對(duì)象流。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-644669.html
public class CitationTest1 {
public static void main(String[] args) throws Exception {
Citation c1 = new Citation();
Student stu = new Student("張三", "西安");
c1.setStu(stu);
//創(chuàng)建對(duì)象輸出流對(duì)象
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("C:\\Users\\Think\\Desktop\\b.txt"));
//將c1對(duì)象寫(xiě)出到文件中
oos.writeObject(c1);
oos.close();
//創(chuàng)建對(duì)象出入流對(duì)象
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("C:\\Users\\Think\\Desktop\\b.txt"));
//讀取對(duì)象
Citation c2 = (Citation) ois.readObject();
//獲取c2獎(jiǎng)狀所屬學(xué)生對(duì)象
Student stu1 = c2.getStu();
stu1.setName("李四");
//判斷stu對(duì)象和stu1對(duì)象是否是同一個(gè)對(duì)象
System.out.println("stu和stu1是同一個(gè)對(duì)象?" + (stu == stu1));
c1.show();
c2.show();
}
}
運(yùn)行結(jié)果為:
注意:Citation類(lèi)和Student類(lèi)必須實(shí)現(xiàn)Serializable接口,否則會(huì)拋NotSerializableException異常。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-644669.html
到了這里,關(guān)于創(chuàng)建型模式-原型模式的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!