Java設(shè)計(jì)模式之原型模式詳細(xì)解析
一、原型模式
1. 概述
用一個(gè)已經(jīng)創(chuàng)建的實(shí)例作為原型,通過(guò)復(fù)制該原型對(duì)象來(lái)創(chuàng)建一個(gè)和原型對(duì)象相同的新對(duì)象。
2. 結(jié)構(gòu)
原型模式包含如下角色:
抽象原型類:規(guī)定了具體原型對(duì)象必須實(shí)現(xiàn)的 clone() 方法。具體原型類:實(shí)現(xiàn)抽象原型類的 clone() 方法,它是可被復(fù)制的對(duì)象。訪問(wèn)類:使用具體原型類中的 clone() 方法來(lái)復(fù)制新的對(duì)象。
接口類圖如下:
3. 實(shí)現(xiàn)
原型模式的克隆分為淺克隆和深克隆。
- 淺克?。簞?chuàng)建一個(gè)新對(duì)象,新對(duì)象的屬性和原來(lái)對(duì)象完全相同,對(duì)于非基本類型屬性,仍指向原有屬性所指向的對(duì)象的內(nèi)存地址。
- 深克隆:創(chuàng)建一個(gè)新對(duì)象,屬性中引用的其他對(duì)象也會(huì)被克隆,不再指向原有對(duì)象地址。
Java中的Object類中提供了 clone() 方法來(lái)實(shí)現(xiàn)淺克隆。
Cloneable 接口是上面的類圖中的抽象原型類,而實(shí)現(xiàn)了Cloneable接口的子實(shí)現(xiàn)類就是具體的原型類。
Realizetype(具體的原型類):
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)類):
public class PrototypeTest { public static void main(String[] args) throws CloneNotSupportedException { //創(chuàng)建一個(gè)原型類對(duì)象 Realizetype realizetype = new Realizetype(); //調(diào)用Realizetype類中的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)狀類:
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)類:
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é)果為:
5 使用場(chǎng)景
- 對(duì)象的創(chuàng)建非常復(fù)雜,可以使用原型模式快捷的創(chuàng)建對(duì)象。
- 性能和安全要求比較高。
6 擴(kuò)展(深克?。?/h3>
將上面的“三好學(xué)生”獎(jiǎng)狀的案例中Citation類的name屬性修改為Student類型的屬性。
獎(jiǎng)狀類:
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é)生類:
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è)試類:
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ì)具體原型類(Citation)中的引用類型的屬性進(jìn)行引用的復(fù)制。
這種情況需要使用深克隆,而進(jìn)行深克隆需要使用對(duì)象流。
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類和Student類必須實(shí)現(xiàn)Serializable接口,否則會(huì)拋NotSerializableException異常。
到此這篇關(guān)于Java設(shè)計(jì)模式之原型模式詳細(xì)解析的文章就介紹到這了,更多相關(guān)Java中的原型模式內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java?kafka如何動(dòng)態(tài)設(shè)置用戶讀寫(xiě)權(quán)限
這篇文章主要介紹了java?kafka如何動(dòng)態(tài)設(shè)置用戶讀寫(xiě)權(quán)限問(wèn)題,具有很好的參考家價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-08-08Java下3中XML解析 DOM方式、SAX方式和StAX方式
目前我知道的JAVA解析XML的方式有:DOM, SAX, StAX;如果選用這幾種,感覺(jué)還是有點(diǎn)麻煩;如果使用:JAXB(Java Architecture for XML Binding),個(gè)人覺(jué)得太方便了2013-04-04Java 獲取網(wǎng)絡(luò)302重定向URL的方法
在本篇文章里小編給大家整理的是關(guān)于Java 獲取網(wǎng)絡(luò)302重定向URL的方法以及相關(guān)知識(shí)點(diǎn),有興趣的朋友們參考下。2019-08-08java中File類的三種創(chuàng)建文件夾方法總結(jié)
這篇文章主要給大家介紹了關(guān)于java中File類的三種創(chuàng)建文件夾方法,File類代表文件或目錄路徑名的抽象表達(dá)形式,通過(guò)File類提供的方法,我們可以很方便地創(chuàng)建文件夾,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-04-04詳解java==運(yùn)算符和equals()方法的區(qū)別
這篇文章主要介紹了java==運(yùn)算符和equals()方法的區(qū)別,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-03-03MyBatisPlus3如何向數(shù)據(jù)庫(kù)中存入List
本文主要介紹了Mybatis Plus的類型處理器的使用,通過(guò)User.java和UserMapper.xml示例進(jìn)行詳細(xì)的解析,并提供了JSON解析器的使用方法,希望通過(guò)這篇文章,可以幫助大家更好的理解和掌握Mybatis Plus的類型處理器2024-10-10java基礎(chǔ)之?dāng)?shù)組常用操作總結(jié)(必看篇)
下面小編就為大家?guī)?lái)一篇java基礎(chǔ)之?dāng)?shù)組常用操作總結(jié)(必看篇)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-06-06