




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、設(shè)計(jì)模式 原型(Prototype)模式 Session3 By 1st Jul 20081原型(Prototype)模式通過給出一個(gè)原型對(duì)象來指明所要?jiǎng)?chuàng)建的對(duì)象類型,然后用拷貝這個(gè)原型對(duì)象的辦法創(chuàng)建出更多的同類型對(duì)象。 孫大圣的毫毛 孫悟空在與黃風(fēng)怪的戰(zhàn)斗中,“使一個(gè)身外身的手段:把毫毛揪下一把,用口嚼得粉碎,望上一噴,叫聲變,變有百十個(gè)行者,都是一樣得打扮,各執(zhí)一根鐵棒,把那怪圍在空中。”換而言之,孫悟空可以根據(jù)自己的形象,拷貝出很多“身外身”來。 孫悟空這種身外身的手段在面向?qū)ο笤O(shè)計(jì)領(lǐng)域里叫原型(Prototype)模式。21,Java對(duì)原型模式的支持 在Java里面,我們可以通過Clo
2、ne()方法實(shí)現(xiàn)原型模式。任何類,只要想支持克隆,必須實(shí)現(xiàn)Cloneable接口。Cloneable接口中有Clone方法,可以在類中復(fù)寫實(shí)現(xiàn)自定義的克隆方法??寺〉膶?shí)現(xiàn)方法有三種:淺拷貝、深拷貝和完全拷貝。(1)淺拷貝被拷貝對(duì)象的所有變量都含有與原來的對(duì)象相同的值,而所有的對(duì)其他對(duì)象的引用仍然指向原來的對(duì)象。換言之,淺拷貝僅僅拷貝所考慮的對(duì)象,而不拷貝它所引用的對(duì)象。 (2)深拷貝 被拷貝對(duì)象的所有變量都含有與原來的對(duì)象相同的值,除去那些引用其他對(duì)象的變量。那些引用其他對(duì)象的變量將指向被拷貝過的新對(duì)象,而不再是原有的那些被引用的對(duì)象。換言之,深拷貝把要拷貝的對(duì)象所引用的對(duì)象都拷貝了一遍。 (
3、3)完全拷貝 完全拷貝不僅把要拷貝的對(duì)象所直接引用的對(duì)象都拷貝了一遍, 還把該對(duì)象間接引用到的所有對(duì)象也都拷貝了一遍。這是最徹底的一種拷貝。32,Java的clone()方法 Cloneprotected Object clone() throws CloneNotSupportedException This method may be called to create a new copy of the Object. The typical behavior is as follows:o = o.clone() is falseo.getClass() = o.clone().getC
4、lass() is trueo.equals(o) is trueHowever, these are not strict requirements, and may be violated if necessary. Of the three requirements, the last is the most commonly violated, particularly if the subclass does not override equals(Object) 55 . If the Object you call clone() on does not implement Cl
5、oneable (which is a placeholder interface), then a CloneNotSupportedException is thrown. Notice that Object does not implement Cloneable; this method exists as a convenience for subclasses that do. Objects implementation of clone allocates space for the new Object using the correct class, without ca
6、lling any constructors, and then fills in all of the new field values with the old field values. Thus, it is a shallow copy. However, subclasses are permitted to make a deep copy. All array types implement Cloneable, and override this method as follows (it should never fail):public Object clone() tr
7、y super.clone(); catch (CloneNotSupportedException e) throw new InternalError(e.getMessage(); 42,Java的clone()方法 clone方法將對(duì)象復(fù)制了一份并返回給調(diào)用者。一般而言,clone()方法滿足:對(duì)任何的對(duì)象x,都有x.clone() !=x 克隆對(duì)象與原對(duì)象不是同一個(gè)對(duì)象對(duì)任何的對(duì)象x,都有x.clone().getClass()=x.getClass() 克隆對(duì)象與原對(duì)象的類型一樣如果對(duì)象x的equals()方法定義恰當(dāng),那么 x.clone().equals(x)應(yīng)該成立。Java
8、中對(duì)象的克隆為了獲取對(duì)象的一份拷貝,我們可以利用Object類的clone()方法。在派生類中覆蓋基類的clone()方法,并聲明為public。在派生類的clone()方法中,調(diào)用super.clone()。在派生類中實(shí)現(xiàn)Cloneable接口。 53,Java的類拷貝實(shí)現(xiàn)代碼class Student implements Cloneable String name;int age; Student(String name,int age) =name;this.age=age; public Object clone() Object o=null;try o=(Stu
9、dent)super.clone();/Object中的clone()識(shí)別出你要復(fù)制的是哪一個(gè)對(duì)象。 catch(CloneNotSupportedException e) System.out.println(e.toString(); return o; public static void main(String args) Student s1=new Student(“zhangsan”,18); Student s2=(Student)s1.clone(); =“l(fā)isi”; s2.age=20; System.out.println(“name=”++
10、“,”+“age=”+s1.age);/修改學(xué)生2后,不影響學(xué)生1的值。 為什么我們?cè)谂缮愔懈采wObject的clone()方法時(shí),一定要調(diào)用super.clone()呢?在運(yùn)行時(shí)刻,Object中的 clone()識(shí)別出你要復(fù)制的是哪一個(gè)對(duì)象,然后為此對(duì)象分配空間,并進(jìn)行對(duì)象的復(fù)制,將原始對(duì)象的內(nèi)容一一復(fù)制到新對(duì)象的存儲(chǔ)空間中。繼承自java.lang.Object類的clone()方法是淺復(fù)制。后面的代碼可以證明。淺拷貝63,Java的類拷貝實(shí)現(xiàn)代碼class Professor String name;int age; Professor(String name,int age) th
11、=name;this.age=age; class Student implements Cloneable String name;/常量對(duì)象。int age; Professor p;/學(xué)生1和學(xué)生2的引用值都是一樣的。 Student(String name,int age,Professor p) =name;this.age=age;this.p=p; public Object clone() Student o=null;try o=(Student)super.clone(); catch(CloneNotSupportedException e
12、) System.out.println(e.toString(); /o.p=(Professor)p.clone();return o; public static void main(String args) Professor p=new Professor(wanGWu,50); Student s1=new Student(zhangsan,18,p); Student s2=(Student)s1.clone(); =lisi; s2.p.age=30;System.out.println(name=++,+age=+s1.p.age);/學(xué)生
13、1的教授為lisi,age為30,被改了淺拷貝73,Java的類拷貝實(shí)現(xiàn)代碼class Professor implements Cloneable String name;int age; Professor(String name,int age) =name;this.age=age; public Object clone() Object o=null;try o=super.clone(); catch(CloneNotSupportedException e) System.out.println(e.toString(); return o; class St
14、udent implements Cloneable String name;/常量對(duì)象。int age; Professor p;/學(xué)生1和學(xué)生2的引用值都是一樣的。 Student(String name,int age,Professor p) =name;this.age=age;this.p=p; public Object clone() Student o=null;try o=(Student)super.clone(); catch(CloneNotSupportedException e) System.out.println(e.toString();
15、o.p=(Professor)p.clone();return o; public static void main(String args) Professor p=new Professor(“wanGWu”,50); Student s1=new Student(“zhangsan”,18,p); Student s2=(Student)s1.clone(); =“l(fā)isi”; s2.p.age=30;System.out.println(“name=”++“,”+“age=”+s1.p.age);/學(xué)生1的教授不改變深拷貝83,Java的類拷貝實(shí)現(xiàn)代
16、碼class Professor implements Serializable String name;int age; Professor(String name,int age) =name;this.age=age; class Student implements Serializable String name;/常量對(duì)象。int age; Professor p;/學(xué)生1和學(xué)生2的引用值都是一樣的。 Student(String name,int age,Professor p) =name;this.age=age;this.p=p; pub
17、lic Object fullClone() throws IOException,OptionalDataException,ClassNotFoundException/將對(duì)象寫到流里ByteArrayOutoutStream bo=new ByteArrayOutputStream();ObjectOutputStream oo=new ObjectOutputStream(bo);oo.writeObject(this);/從流里讀出來ByteArrayInputStream bi=new ByteArrayInputStream(bo.toByteArray();ObjectInpu
18、tStream oi=new ObjectInputStream(bi);return(oi.readObject();public static void main(String args) Professor p=new Professor(wangwu,50); Student s1=new Student(zhangsan,18,p); Student s2=(Student)s1.fullClone(); =lisi; s2.p.age=30;System.out.println(name=++,+age=+s1.p.age); /學(xué)生1的教授不改
19、變。完全拷貝在Java語言里深復(fù)制一個(gè)對(duì)象,常常可以先使對(duì)象實(shí)現(xiàn)Serializable接口,然后把對(duì)象(實(shí)際上只是對(duì)象的一個(gè)拷貝)寫到一個(gè)流里(腌成干菜),再從流里讀出來(把干菜回鮮),便可以重建對(duì)象。94,Prototype模式的結(jié)構(gòu)客戶(Client)角色:客戶類提出創(chuàng)建對(duì)象的請(qǐng)求。抽象原型(Prototype)角色:這是一個(gè)抽象角色,通常由一個(gè)接口類或抽象類實(shí)現(xiàn)。此角色給出所有的具體原型類所需的接口。在Java中,抽象原型角色通常實(shí)現(xiàn)了Cloneable接口。具體原型(Concrete Prototype)角色:被復(fù)制的對(duì)象。此角色需要實(shí)現(xiàn)抽象原型角色所要求的接口。104.1 Prot
20、otype模式實(shí)現(xiàn) - 抽象原型public abstract class AbstractSpoon implements Cloneable String spoonName; public void setSpoonName(String spoonName) this.spoonName = spoonName; public String getSpoonName() return this.spoonName; public Object clone() Object object = null; try object = super.clone(); catch (CloneNo
21、tSupportedException exception) System.err.println(AbstractSpoon is not Cloneable); return object; 114.2 Prototype模式實(shí)現(xiàn) - 具體原型public class SaladSpoon extends AbstractSpoon public SaladSpoon() setSpoonName(Salad Spoon); public class SoupSpoon extends AbstractSpoon public SoupSpoon() setSpoonName(Soup S
22、poon); 124.3 Prototype模式實(shí)現(xiàn) - 客戶 public class Client /* * param args */public static void main(String args) AbstractSpoon spoon1 = new SoupSpoon();AbstractSpoon spoon2 = (AbstractSpoon) spoon1.clone(); System.out.println(spoon2.getSpoonName();AbstractSpoon spoon3 = new SaladSpoon();AbstractSpoon spoo
23、n4 = (AbstractSpoon) spoon3.clone(); System.out.println(spoon4.getSpoonName();135,帶原型管理器的原型模式 客戶(Client)角色:客戶端類向原型管理器提出創(chuàng)建對(duì)象的請(qǐng)求。抽象原型(Prototype)角色:這是一個(gè)抽象角色,通常由一個(gè)接口或抽象類實(shí)現(xiàn)。此角色給出所有的具體原型類所需的接口。在Java中,抽象原型角色通常實(shí)現(xiàn)了Cloneable接口。具體原型(Concrete Prototype)角色:被復(fù)制的對(duì)象。此角色需要實(shí)現(xiàn)抽象的原型角色所要求的接口。原型管理器(Prototype Manager)角色:創(chuàng)
24、建具體原型類的對(duì)象,并記錄每一個(gè)被創(chuàng)建的對(duì)象。 145.1 帶原型管理器的原型模式實(shí)現(xiàn) 原型管理器import java.util.HashMap;public class SpoonManager private HashMap hm = null;private static SpoonManager spoonManager = null;private SpoonManager() hm = new HashMap();public static synchronized SpoonManager getSpoonManager() if(spoonManager = null) sp
25、oonManager = new SpoonManager(); return spoonManager;public void register(String name, Object prototype)hm.put(name,prototype);public void unRegister(String name) hm.remove(name); public Object getSpoon(String name) Object o = null; if(hm.containsKey(name) o = hm.get(name); else try/自動(dòng)查找原型管理器里不存在的類,
26、并動(dòng)態(tài)生成它 o = Class.forName(name).newInstance(); this.register(name,o); catch(Exception e) System.out.println(class +name+ dont define +e.getMessage(); e.printStackTrace(); return (AbstractSpoon)o).clone(); 155.2 帶原型管理器的原型模式實(shí)現(xiàn) 客戶public class Client /* * param args */public static void main(String args)
27、 AbstractSpoon soupSpoon = new SoupSpoon();AbstractSpoon saladSpoon = new SaladSpoon();SpoonManager spoonManager = SpoonManager.getSpoonManager();spoonManager.register(prototype.test.SoupSpoon, soupSpoon);spoonManager.register(prototype.test.SaladSpoon, saladSpoon);AbstractSpoon soupSpoon2 = (Abstra
28、ctSpoon) spoonManager.getSpoon(prototype.test.SoupSpoon);AbstractSpoon saladSpoon2 = (AbstractSpoon) spoonManager.getSpoon(prototype.test.SaladSpoon);System.out.println(soupSpoon.hashCode();System.out.println(soupSpoon2.hashCode();System.out.println(saladSpoon.hashCode();System.out.println(saladSpoo
29、n2.hashCode();166, JavaScript中的prototype應(yīng)用 下面是一個(gè)比較實(shí)際的web應(yīng)用中的例子,通過現(xiàn)有的dom元素對(duì)象,創(chuàng)建了一個(gè)新的副本。這個(gè)副本dom元素并沒有使用document.createElement方法創(chuàng)建。 TestDivvar testClone = document.getElementById(test).cloneNode(true);document.body.appendChild(testClone); 176, JavaScript中的prototype應(yīng)用淺拷貝function Writer (name, sex) this.n
30、ame = name; this.sex = sex;function Book (name, pages, price, writer) = name; this.pages = pages; this.price = price; this.writer = writer;Btotype.clone = function () /深拷貝淺拷貝的區(qū)別就在這個(gè)function里 return new Book(, this.pages, this.price, this.writer);var writer = new Writer(佘丹,
31、男);var bookName = 深入解析原型模式;var myBook = new Book(bookName, 611, 70, writer);var otherBook = myBook.clone();myB = 不是深入解析原型模式; /值類型的修改不會(huì)相互影響alert(myB,otherB);/所以這里打?。翰皇巧钊虢馕鲈湍J?,深入解析原型模式myB = 不是佘丹; /引用類型的修改會(huì)相互影響,因?yàn)樗麄円猛瑐€(gè)內(nèi)存地址alert(myB, otherBook.writ
32、);/所以這里打?。翰皇琴艿?,不是佘丹186, JavaScript中的prototype應(yīng)用深拷貝function Writer (name, sex) = name; this.sex = sex;function Book (name, pages, price, writer) = name; this.pages = pages; this.price = price; this.writer = writer;Btotype.clone = function () /深拷貝淺拷貝的區(qū)別就在這個(gè)function里 v
33、ar writer = new Writer(,this.writer.sex); return new Book(, this.pages, this.price, writer);var writer = new Writer(佘丹, 男);var bookName = 深入解析原型模式;var myBook = new Book(bookName, 611, 70, writer);var otherBook = myBook.clone();myB = 不是深入解析原型模式; /值類型的修改不會(huì)相互影響alert(myB
34、,otherB);/所以這里打?。翰皇巧钊虢馕鲈湍J?,深入解析原型模式myB = 不是佘丹; /深拷貝,引用已經(jīng)指向不同內(nèi)存地址,修改不會(huì)相互影響alert(myB, otherB);/所以這里打?。翰皇琴艿?,佘丹196, JavaScript中的prototype應(yīng)用原型管理器StyleTestfunction StyleItem (fontSize, color) /類定義 this.fontSize = fontSize; this.color = color;St
35、yleItotype.clone = function () return fontSize:this.fontSize, color:this.color var StyleManager = /原型管理器 getStyle: function (key) if (thiskey) return thiskey.clone(); ;/預(yù)創(chuàng)建類可能的狀態(tài)集合對(duì)象StyleManagerbig = new StyleItem(16px, #000);StyleManagernormal = new StyleItem(14px, #333);StyleManagersmall =
36、new StyleItem(12px, #666);/無需再通過new來創(chuàng)建StyleItem類的對(duì)象了var el = document.getElementById(styletest);var style = StyleManager.getStyle(small);for (var k in style)el.stylek = stylek; 207, 深入JavaScript的prototype Javascript中的面向?qū)ο髾C(jī)制是通過prototype實(shí)現(xiàn)的,在new一個(gè)對(duì)象的時(shí)候,其實(shí)并沒有為每一個(gè)對(duì)象創(chuàng)建每個(gè)prototype成員的副本,而是將對(duì)象成員指針指向prototyp
37、e成員,下面程序可以驗(yàn)證這點(diǎn):function Test () Ttotype.alert = function () alert(test);var test1 = new Test();var test2 = new Test();alert(test1.alert = test2.alert);totype.alert = function () alert(test1);test2.alert(); 217, 深入JavaScript的prototype 此外,JScript中對(duì)象的prototype屬性,是用來返回對(duì)象類型原型的引用的。所有 JScript 內(nèi)部對(duì)象都有只讀的 prototype 屬性 ,但可以向其原型中動(dòng)態(tài)添加功能(屬性和方法),而且對(duì)象的新實(shí)例會(huì)“繼承”賦予該對(duì)象原型的操作。 下面是三個(gè)經(jīng)典的prototype屬性的使用示例。 1、為腳本環(huán)境內(nèi)建對(duì)象添加方法:Stotype.trim() return this.replace(/(s )|(s $)/g, ); 2、為用戶自定義類添加方法: function TestObject(name) this.m
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 樓頂?shù)跹b字體施工方案
- 教師節(jié)感恩作文
- 2025年度校園心理安全責(zé)任協(xié)議書
- 2025年度智能化支付解決方案與服務(wù)合同
- 二零二五年度實(shí)習(xí)教師實(shí)習(xí)崗位工作職責(zé)合同
- 二零二五年度能源合同履約金管理及能源節(jié)約措施
- 二零二五年度農(nóng)村房產(chǎn)轉(zhuǎn)讓合同(附帶農(nóng)村土地經(jīng)營權(quán))
- 2025年度金融衍生品交易連帶責(zé)任保證合同
- 二零二五年度風(fēng)險(xiǎn)評(píng)估與風(fēng)險(xiǎn)控制合同
- 2025年度集體合同簽訂與產(chǎn)業(yè)工人隊(duì)伍建設(shè)
- 2025年湖南工業(yè)職業(yè)技術(shù)學(xué)院?jiǎn)握新殬I(yè)傾向性測(cè)試題庫含答案
- 2025年中國煙氣檢測(cè)儀器行業(yè)市場(chǎng)運(yùn)行態(tài)勢(shì)、進(jìn)出口貿(mào)易及發(fā)展趨勢(shì)預(yù)測(cè)報(bào)告
- 社會(huì)企業(yè)參與養(yǎng)老服務(wù)的模式與效果
- 減免保證金申請(qǐng)書
- 2025年執(zhí)業(yè)醫(yī)師定期考核題庫及參考答案
- 五年級(jí)下冊(cè)語文第三單元遨游漢字王國單元整體教學(xué)設(shè)計(jì)
- 高一上學(xué)期統(tǒng)編版(2019)必修中外歷史綱要上翻書大賽課件
- GB 39752-2024電動(dòng)汽車供電設(shè)備安全要求
- GB/T 3452.1-2005液壓氣動(dòng)用O形橡膠密封圈第1部分:尺寸系列及公差
- 地下連續(xù)墻鋼筋籠吊裝方案及吊裝驗(yàn)算書
- 病理學(xué):腫瘤學(xué)習(xí)教案
評(píng)論
0/150
提交評(píng)論