Java?設(shè)計(jì)模式以虹貓藍(lán)兔的故事講解原型模式
什么是原型模式
原型(Prototype)模式的定義如下: 用一個(gè)已經(jīng)創(chuàng)建的實(shí)例作為原型,通過復(fù)制該原型對象來創(chuàng)建一個(gè)和原型相同或相似的新對象。在這里,原型實(shí)例指定了要?jiǎng)?chuàng)建的對象的種類。用這種方式創(chuàng)建對象非常高效,根本無須知道對象創(chuàng)建的細(xì)節(jié)。例如,Windows 操作系統(tǒng)的安裝通常較耗時(shí),如果復(fù)制就快了很多。在生活中復(fù)制的例子非常多,這里不一一列舉了。
優(yōu)點(diǎn)
1、Java 自帶的原型模式基于內(nèi)存二進(jìn)制流的復(fù)制,在性能上比直接 new 一個(gè)對象更加優(yōu)良。
2、可以使用深克隆方式保存對象的狀態(tài),使用原型模式將對象復(fù)制一份,并將其狀態(tài)保存起來,簡化了創(chuàng)建對象的過程,以便在需要的時(shí)候使用(例如恢復(fù)到歷史某一狀態(tài)),可輔助實(shí)現(xiàn)撤銷操作。
缺點(diǎn)
1、需要為每一個(gè)類都配置一個(gè) clone 方法
2、clone 方法位于類的內(nèi)部,當(dāng)對已有類進(jìn)行改造的時(shí)候,需要修改代碼,違背了開閉原則。
3、當(dāng)實(shí)現(xiàn)深克隆時(shí),需要編寫較為復(fù)雜的代碼,而且當(dāng)對象之間存在多重嵌套引用時(shí),為了實(shí)現(xiàn)深克隆,每一層對象對應(yīng)的類都必須支持深克隆,實(shí)現(xiàn)起來會比較麻煩。因此,深克隆、淺克隆需要運(yùn)用得當(dāng)。
應(yīng)用場景
在有些系統(tǒng)中,存在大量相同或相似對象的創(chuàng)建問題,如果用傳統(tǒng)的構(gòu)造函數(shù)來創(chuàng)建對象,會比較復(fù)雜且耗時(shí)耗資源,用原型模式生成對象就很高效,就像孫悟空拔下猴毛輕輕一吹就變出很多孫悟空一樣簡單。
淺克隆
案例:克隆虹貓
淺克隆一個(gè)虹貓,外表特征一樣,但是只有一個(gè)靈魂。
克隆虹貓身體受到傷害,本體虹貓不受影響。
克隆虹貓精神受到傷害,本體虹貓也受到同樣的傷害。
代碼實(shí)現(xiàn)
虹貓靈魂?duì)顟B(tài)類
這里聲明了虹貓的靈魂?duì)顟B(tài)
public class Hong { //虹貓的靈魂?duì)顟B(tài) private String lh; Hong(String lh) { this.lh = lh; } Hong() { } public String getLh() { return lh; } public void setLh(String lh) { this.lh = lh; } }
虹貓個(gè)體類
實(shí)現(xiàn)了Cloneable 接口,并且有虹貓的身體狀態(tài)和靈魂?duì)顟B(tài)等屬性。
public class Qian implements Cloneable { private String shou; private String jiao; private String yan; private Hong hong; Qian() { } Qian(String shou, String jiao, String yan, Hong hong) { this.hong = hong; this.shou = shou; this.jiao = jiao; this.yan = yan; } public Qian clone() throws CloneNotSupportedException { return (Qian) super.clone(); } public String getShou() { return shou; } public void setShou(String shou) { this.shou = shou; } public String getJiao() { return jiao; } public void setJiao(String jiao) { this.jiao = jiao; } public String getYan() { return yan; } public void setYan(String yan) { this.yan = yan; } public Hong getHong() { return hong; } public void setHong(Hong hong) { this.hong = hong; } }
測試類
這里測試一下淺克隆的效果:
淺克隆一個(gè)虹貓,外表特征一樣,但是只有一個(gè)靈魂。
克隆虹貓身體受到傷害,本體虹貓不受影響。
克隆虹貓精神受到傷害,本體虹貓也受到同樣的傷害。
public class Demo { public static void main(String[] args) throws CloneNotSupportedException { Qian qian = new Qian("兩只手", "兩只腳", "兩只眼", new Hong("完整的靈魂")); Qian qian1 = qian.clone(); System.out.printf("虹貓少俠本體的身體狀態(tài):%s,%s,%s,%s,", qian.getHong().getLh(), qian.getJiao(), qian.getShou(), qian.getYan()); System.out.println(); System.out.printf("虹貓少俠一號的身體狀態(tài):%s,%s,%s,%s,", qian1.getHong().getLh(), qian1.getJiao(), qian1.getShou(), qian1.getYan()); } }
克隆出來了一個(gè)虹貓一號,所有屬性都一模一樣
public class Demo { public static void main(String[] args) throws CloneNotSupportedException { Qian qian = new Qian("兩只手", "兩只腳", "兩只眼", new Hong("完整的靈魂")); Qian qian1 = qian.clone(); qian1.getHong().setLh("靈魂受到攻擊"); qian1.setJiao("斷了一只腳"); System.out.printf("虹貓少俠本體的身體狀態(tài):%s,%s,%s,%s,", qian.getHong().getLh(), qian.getJiao(), qian.getShou(), qian.getYan()); System.out.println(); System.out.printf("虹貓少俠一號的身體狀態(tài):%s,%s,%s,%s,", qian1.getHong().getLh(), qian1.getJiao(), qian1.getShou(), qian1.getYan()); } }
這里克隆虹貓的腳和靈魂都受到了傷害,本體虹貓的身體沒有受到影響,但是靈魂卻受到了傷害。
總結(jié)
一、為什么淺克隆中虹貓一號的腳受到了傷害,本體虹貓卻沒受到傷害?
二、為什么淺克隆中虹貓一號的靈魂受到了傷害,本體虹貓也受到了傷害?
因?yàn)閯?chuàng)建一個(gè)新對象,新對象的屬性和原來對象完全相同,對于非基本類型屬性,仍指向原有屬性所指向的對象的內(nèi)存地址。 兩個(gè)虹貓的靈魂指向同一個(gè)內(nèi)存地址,所以存儲的是同一個(gè)靈魂。
深克隆
案例:克隆虹貓
深克隆一個(gè)虹貓,外表特征一樣,都有獨(dú)立靈魂。
克隆虹貓身體受到傷害,本體虹貓不受影響。
克隆虹貓精神受到傷害,本體虹貓也不受影響。
代碼實(shí)現(xiàn)
虹貓靈魂?duì)顟B(tài)類
這里聲明了虹貓的靈魂?duì)顟B(tài),并且實(shí)現(xiàn)了Cloneable 接口,克隆一個(gè)虹貓靈魂
public class Hong implements Cloneable { //虹貓的靈魂?duì)顟B(tài) private String lh; Hong(String lh) { this.lh = lh; } Hong() { } public Hong clone() throws CloneNotSupportedException { return (Hong) super.clone(); } public String getLh() { return lh; } public void setLh(String lh) { this.lh = lh; } }
虹貓個(gè)體類
重寫了clone方法,在clone方法中調(diào)用了hong.clone()方法克隆了一個(gè)虹貓靈魂
public class Qian implements Cloneable { private String shou; private String jiao; private String yan; private Hong hong; Qian() { } Qian(String shou, String jiao, String yan, Hong hong) { this.hong = hong; this.shou = shou; this.jiao = jiao; this.yan = yan; } public Qian clone() throws CloneNotSupportedException { Qian qian = (Qian) super.clone(); hong = hong.clone(); return qian; } public String getShou() { return shou; } public void setShou(String shou) { this.shou = shou; } public String getJiao() { return jiao; } public void setJiao(String jiao) { this.jiao = jiao; } public String getYan() { return yan; } public void setYan(String yan) { this.yan = yan; } public Hong getHong() { return hong; } public void setHong(Hong hong) { this.hong = hong; } }
測試類
這里測試一下淺克隆的效果:
深克隆一個(gè)虹貓,外表特征一樣,都有獨(dú)立靈魂。
克隆虹貓身體受到傷害,本體虹貓不受影響。
克隆虹貓精神受到傷害,本體虹貓也不受影響。
public class Demo { public static void main(String[] args) throws CloneNotSupportedException { Qian qian = new Qian("兩只手", "兩只腳", "兩只眼", new Hong("完整的靈魂")); Qian qian1 = qian.clone(); qian1.getHong().setLh("靈魂受到攻擊"); qian1.setJiao("斷了一只腳"); System.out.printf("虹貓少俠本體的身體狀態(tài):%s,%s,%s,%s,", qian.getHong().getLh(), qian.getJiao(), qian.getShou(), qian.getYan()); System.out.println(); System.out.printf("虹貓少俠一號的身體狀態(tài):%s,%s,%s,%s,", qian1.getHong().getLh(), qian1.getJiao(), qian1.getShou(), qian1.getYan()); } }
深克隆出的虹貓完全是個(gè)獨(dú)立的個(gè)體,再也不用受限制了。
總結(jié)
深克?。簞?chuàng)建一個(gè)新對象,屬性中引用的其他對象也會被克隆,不再指向原有對象地址。
到此這篇關(guān)于Java 設(shè)計(jì)模式以虹貓藍(lán)兔的故事講解原型模式的文章就介紹到這了,更多相關(guān)Java 原型模式內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Javacv使用ffmpeg實(shí)現(xiàn)音視頻同步播放
這篇文章主要介紹了Javacv使用ffmpeg實(shí)現(xiàn)音視頻同步播放,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-12-12Java數(shù)據(jù)結(jié)構(gòu)之平衡二叉樹的原理與實(shí)現(xiàn)
平衡樹(Balance Tree,BT) 指的是,任意節(jié)點(diǎn)的子樹的高度差都小于等于1。常見的符合平衡樹的有,B樹(多路平衡搜索樹)、AVL樹(二叉平衡搜索樹)等。本文將詳細(xì)介紹平衡二叉樹的概念和實(shí)現(xiàn)原理以及它的實(shí)現(xiàn)2022-01-01Spring連接Mysql數(shù)據(jù)庫的實(shí)現(xiàn)步驟
本文主要介紹了Spring連接Mysql數(shù)據(jù)庫的實(shí)現(xiàn)步驟,文中根據(jù)實(shí)例編碼詳細(xì)介紹的十分詳盡,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03postman中實(shí)現(xiàn)傳遞@RequestBody參數(shù)
這篇文章主要介紹了postman中實(shí)現(xiàn)傳遞@RequestBody參數(shù),具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-10-10JavaGUI事件監(jiān)聽機(jī)制超詳細(xì)講解
Java事件監(jiān)聽器是由事件類和監(jiān)聽接口組成,自定義一個(gè)事件前,必須提供一個(gè)事件的監(jiān)聽接口以及一個(gè)事件類。JAVA中監(jiān)聽接口是繼承java.util.EventListener的類,事件類繼承java.util.EventObject的類2023-03-03webuploader在springMVC+jquery+Java開發(fā)環(huán)境下的大文件分片上傳的實(shí)例代碼
這篇文章主要介紹了webuploader在springMVC+jquery+Java開發(fā)環(huán)境下的大文件分片上傳的實(shí)例代碼,需要的朋友可以參考下2017-04-04