日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

原型模式codeing

發(fā)布時間:2024/4/13 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 原型模式codeing 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
我們還是引入一個業(yè)務(wù)場景,在網(wǎng)上是經(jīng)常是有活動的,例如說積分抽獎,或者說做一些手機的活動,而這種情況呢,會發(fā)一些郵件,那我們假設(shè)這個郵件對象,非常非常繁瑣,當然呢在我們的例子中,不會那么繁瑣的,這里面就可以體現(xiàn),原型模式的一個架子,那很簡單,我們先創(chuàng)建一個類 package com.learn.design.pattern.creational.prototype;/*** 這里面有幾個屬性* 非常簡單的屬性* 都是String類型* 關(guān)于Mail* 一個是發(fā)送郵件* 另外呢是存儲原始郵件的一個記錄* 我們創(chuàng)建一個Util* * 我們要讓這個類實現(xiàn)克隆的功能* 只要讓他實現(xiàn)Cloneable這個接口* 然后我們再重寫一下克隆方法就可以了* 非常簡單* 這里面有一個override* 這個克隆方法是Object的* * * * @author Leon.Sun**/ public class Mail implements Cloneable{private String name;private String emailAddress;/*** 還有郵件的內(nèi)容* * */private String content;/*** 現(xiàn)在我們再寫一下他的構(gòu)造器* 默認構(gòu)造器寫在這里邊* * */public Mail(){/*** 打印一下"Mail Class Constructor"* 調(diào)用構(gòu)造器的時候就會打印這一行* 那這個構(gòu)造器是類的默認構(gòu)造器* 然后寫一下get/set方法* * */System.out.println("Mail Class Constructor");}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getEmailAddress() {return emailAddress;}public void setEmailAddress(String emailAddress) {this.emailAddress = emailAddress;}public String getContent() {return content;}public void setContent(String content) {this.content = content;}/*** 為了方便我重寫一下toString方法* 查看的時候就會比較方便* * 直接super.toString()* 然后在Test里面打印一下* */@Overridepublic String toString() {return "Mail{" +"name='" + name + '\'' +", emailAddress='" + emailAddress + '\'' +", content='" + content + '\'' +'}'+super.toString();}@Overrideprotected Object clone() throws CloneNotSupportedException {/*** 我們打印一下* 方便測試* clone mail object* 再回到Test里邊* * */System.out.println("clone mail object");/*** 我們可以看到這里面就直接返回了* 利用默認的就可以* 調(diào)用父類的clone方法* 也就是說Object的clone方法* * */return super.clone();} } package com.learn.design.pattern.creational.prototype;import java.text.MessageFormat;/*** 這里面我們就使用靜態(tài)方法就可以了* * * @author Leon.Sun**/ public class MailUtil {/*** 參數(shù)很簡單* * * @param mail*/public static void sendMail(Mail mail){/*** 第一個用name占位* 向什么同學(xué)* 郵件地址* 郵件內(nèi)容占位* 發(fā)送郵件成功* * * */String outputContent = "向{0}同學(xué),郵件地址:{1},郵件內(nèi)容:{2}發(fā)送郵件成功";/*** 我們直接用format* 然后把占位的字符串輸出到這里* 這個發(fā)送郵件的方法就寫完了* * */System.out.println(MessageFormat.format(outputContent,mail.getName(),mail.getEmailAddress(),mail.getContent()));}/*** save原始的OriginMailRecord* 參數(shù)肯定也是Mail* * * * @param mail*/public static void saveOriginMailRecord(Mail mail){/*** 存儲OriginMail* 存儲原始郵件的記錄* 這樣原始郵件的模板就存儲進去了* 接下來就比較簡單* * */System.out.println("存儲originMail記錄,originMail:"+mail.getContent());} } package com.learn.design.pattern.creational.prototype;/*** * @author Leon.Sun**/ public class Test {/*** 首先進主函數(shù)* * * @param args* @throws CloneNotSupportedException*/public static void main(String[] args) throws CloneNotSupportedException {/*** 首先new一個mail出來* * 首先new的時候調(diào)用默認構(gòu)造器* 然后向誰誰誰發(fā)郵件* 最后存儲的郵件是恭喜你* 而不是初始化模板* 那這里面我們只new了一個對象* 在原型模式當中我么要關(guān)注* new一個對象的過程* 假設(shè)new一個mail對象非常非常復(fù)雜* 而且比較消耗性能* 那現(xiàn)在我們想要解決這個問題有一個辦法* 在初始化的時候立刻存儲起來* 下邊開始發(fā)送* 這樣是嗎沒有問題的* 那么還回來* 假設(shè)不放到這里邊* 還有一種辦法* 初始化完成之后* 在這里邊存儲* 那么我是不是可以在for循環(huán)里面new mail呢* 那如果在這里面去new的話* 每次循環(huán)都要去new一次* 那現(xiàn)在我們就引入原型模式* 看如何解決這個問題* 那原型模式是在內(nèi)存中進行二進制流的拷貝* 肯定要比自己new一個對象性能要好很多* 那我們這個mail去構(gòu)造的時候* 比較簡單* 只有三個屬性* 那如果構(gòu)造起來非常麻煩的話* 并且在這個循環(huán)中要產(chǎn)生大量的對象* 那這種情況下* 用原型模式* 是非常合適的* 那我們現(xiàn)在來試一下* 用原型模式如何做* 首先來到Mail這個類里邊* * mail new出來了* 在new的時候調(diào)用mail的構(gòu)造器* 那我們想一下* 克隆也是重新克隆一個對象* 它會調(diào)用構(gòu)造器嗎* 我們看一下* F6* 看一下console* 這一行的日志是在new mail的時候* 而我們在克隆的時候* 并沒有調(diào)用mail的構(gòu)造器* 所以這個是一個知識點* 那克隆的時候調(diào)用了克隆方法* 這行是打印在mail clone實現(xiàn)中的* * * */Mail mail = new Mail();/*** 這個是初始化的模板* * "初始化模板"模板賦值成功* * */mail.setContent("初始化模板");/*** 這里打印一下初始化mail* * */System.out.println("初始化mail:"+mail);/*** 這里面我們發(fā)送10個郵件* * */for(int i = 0;i < 10;i++){/*** 寫一個臨時的mail* 等于什么呢* 用原始的去克隆* 這里面再強轉(zhuǎn)一下* 然后時候克隆出來的mail去set* * */Mail mailTemp = (Mail) mail.clone();/*** 開始setName* 這個name是一個變量* 為了形成變量* 我們直接用for循環(huán)的下標* * */mailTemp.setName("姓名"+i);mailTemp.setEmailAddress("姓名"+i+"@mc.com");/*** 內(nèi)容都一樣* "恭喜您,此次慕課網(wǎng)活動中獎了"* * */mailTemp.setContent("恭喜您,此次慕課網(wǎng)活動中獎了");/*** 把mail傳進來* * 已經(jīng)發(fā)送* 那現(xiàn)在我來debug跟一下* 單步往下走* * 開始sendMail* 我們看一下這兩個對象* 首先mail420* 但是實際的實現(xiàn)我們看一下public String toString() {return getClass().getName() + "@" + Integer.toHexString(hashCode());}name然后后面拼接一個Integer的方法* 把hashCode換成無符號整數(shù)* 把hashCode轉(zhuǎn)成16進制數(shù)* 在IDEA里面debug的時候* 顯示的hashCode把我們剛剛看到的又轉(zhuǎn)換一下* 所以他的位數(shù)非常短* 那在我們這個課程里* 我可以簡單的認為* 如果他們的數(shù)字一樣的話* 代表的是同一個對象* 那mailTemp是多少* 是424* 那之前的呢* 是420* 很明顯他們是不同的對象* 他們在內(nèi)存的空間地址呢* 也是不一樣的* 我們直接F8放過* 看一下日志* 這里可以顯示clone一個發(fā)送一個* 存儲原始的mail* 內(nèi)容也是初始化模板* 和我們預(yù)期一致* 那這個就是非常典型的原型模式的實際應(yīng)用* 那么打印方便呢* 我們把mail的toString方法* 增加一下* 首先初始化出來的mail的地址是16進制* hashCode轉(zhuǎn)成16進制是7852e922* 下邊克隆出來的也都不一樣* 并且最后打印出來的還是初始化模板* 那在原型模式中* 還有 一種常見的使用方法* 他這個類圖比較簡單* 可以自己看一下* 就是通過抽象類* 來實現(xiàn)原型模式* 我們打個比方* * * * */MailUtil.sendMail(mailTemp);/*** 這里克隆完成以后我們也打印一下* * */System.out.println("克隆的mailTemp:"+mailTemp);}/*** 存儲這個原始的Mail* 現(xiàn)在我們來run一下* 存儲原始mail* 是為了存儲初始化mail* 這個mail其實最后一次結(jié)果* 那我們看一下輸出* * 假設(shè)實際的業(yè)務(wù)非常復(fù)雜* 這個就放到最后* 還有記錄一些發(fā)送的結(jié)果* 都記錄到這個原始的mail里邊* 假設(shè)這個是不能動的* 一定要放到最后* 那么我們在循環(huán)里面怎么做呢* 很簡單* * */MailUtil.saveOriginMailRecord(mail);} } package com.learn.design.pattern.creational.prototype.abstractprototype;/*** 我們來創(chuàng)建一個A* 這個類是一個抽象類* 然后通過它來實現(xiàn)克隆接口* 然后重寫克隆方法* 然后再創(chuàng)建一個類B* * * @author Leon.Sun**/ public abstract class A implements Cloneable{/*** 注意這個方法是protected權(quán)限的方法* 我們直接debug一下* 斷點直接來到父類的clone方法* 直接過* 因為這種方式比較常見* 如果我們的業(yè)務(wù)模型可以抽象出來的話* 也可以使用這種方式* 但是實際業(yè)務(wù)開發(fā)中* 用之前的方式比較多* 直接讓目標類來實現(xiàn)克隆接口* 說到克隆咱們就不得不說一下* 深克隆和淺克隆* 原型模式雖然簡單* 但是一旦用不好的話* 很容易產(chǎn)生bug* 那我們創(chuàng)建一個包* clone包* 專門研究一下原型模式的一個克隆* * * */@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();} } package com.learn.design.pattern.creational.prototype.abstractprototype;/*** 他來繼承A抽象類* 那很簡單* A是抽象的原型* 他能克隆* 而B呢繼承A* 他也自然可以克隆的功能* 這也是原型模式中比較常見的* * * * @author Leon.Sun**/ public class B extends A {/*** 我們測一下* * * @param args* @throws CloneNotSupportedException*/public static void main(String[] args) throws CloneNotSupportedException {/*** 直接new一個B出來* * */B b = new B();/*** 調(diào)用b.clone* 拋出一個異常* 這個時候斷點就會打到A的方法中* * */b.clone();} } package com.learn.design.pattern.creational.prototype.clone;import java.util.Date;/*** 首先我們創(chuàng)建一個類pig* 小豬佩奇* 這里面兩個屬性* 一個是小豬佩奇的name* 還有一個是生日birthday* 引入util里面的Date* 寫一下他的get/set方法* 現(xiàn)在讓他來實現(xiàn)克隆接口* * * @author Leon.Sun**/ public class Pig implements Cloneable{private String name;private Date birthday;/*** 寫一下他的構(gòu)造器* 非常簡單* 然后我們再寫一個測試類* * * @param name* @param birthday*/public Pig(String name, Date birthday) {this.name = name;this.birthday = birthday;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Date getBirthday() {return birthday;}public void setBirthday(Date birthday) {this.birthday = birthday;}/*** 重寫Object的克隆方法* 我們就用默認的就可以了* 然后繼續(xù)* * */@Overrideprotected Object clone() throws CloneNotSupportedException {/*** 首先clone把Pig拿到* 強轉(zhuǎn)一下* * */Pig pig = (Pig)super.clone();//深克隆/*** 深克隆* pig.birthday.clone* 然后呢強轉(zhuǎn)* 單獨為這個生日實現(xiàn)他的克隆方法* 這個時候再return這個pig* 非常簡單* 那對于Pig這個類里面* 生日這種引用對象* 也要單獨的進行克隆* 所以我們在使用原型模式的時候* 這個坑一定要注意* 否則很容易引起bug的* 回到Test里邊* * */pig.birthday = (Date) pig.birthday.clone();return pig;}@Overridepublic String toString() {return "Pig{" +"name='" + name + '\'' +", birthday=" + birthday +'}'+super.toString();} } package com.learn.design.pattern.creational.prototype.clone;import java.lang.reflect.InvocationTargetException; import java.util.Date;/*** * @author Leon.Sun**/ public class Test {public static void main(String[] args) throws CloneNotSupportedException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {/*** 首先我們創(chuàng)建一個birthday* 我們就用0就可以了* 0L* 用它的Long的構(gòu)造器* 那肯定是1970年* * */Date birthday = new Date(0L);/*** 然后new一個小豬佩奇* 第一個傳佩奇* 第二個呢傳birthday* * */Pig pig1 = new Pig("佩奇",birthday);/*** 然后克隆一個* 用pig1.clone* 拋出異常* 然后強轉(zhuǎn)* * */Pig pig2 = (Pig) pig1.clone();/*** 那我們現(xiàn)在打印一下pig1* */System.out.println(pig1);/*** 再打印一下pig2* 打印之前為了方便* 我們重寫一下toString方法* 我們run一下看一下結(jié)果* 可以看到這兩個對象輸出的內(nèi)容* 現(xiàn)在是完全一致的* 時間是1970年1月1號8點開始* 名字是一樣的* 我們把Object的toString加到這里邊* super.toString()* 重新打印一下* 結(jié)果出來了* 雖然toString是一樣的* 但是呢這是兩個不同的對象* 可以看到@后面的十六進制呢不一樣的* 那這些前提是我們沒有重寫hashCode* 因為這個16進制* 是和hashCode有關(guān)的* 看起來這是兩個對象* 那我們現(xiàn)在要修改一下pig1對象的生日* * * * */System.out.println(pig2);/*** 我們直接pig1.getBirthday* 然后setTime* 隨便寫一個時間* 1970開始的毫秒數(shù)* 那我們再輸出一下* * * */pig1.getBirthday().setTime(666666666666L);/*** 再重新輸出一下pig1和pig2* 直接run一下* 看一下結(jié)果* 我們預(yù)期只是修改pig1的生日* 我們看一下這個結(jié)果* 首先上邊是輸出調(diào)整生日之前的小豬佩奇* 第二個是克隆出來的* 這個沒有什么問題* 注意在重新設(shè)置pig1的生日之后呢* 下面又輸出了pig1和pig2* 我們看一下這兩個* 我們看一下* 這兩個肯定是同一個對象* 這兩個也是同一個對象* 但是重新設(shè)置完pig1的生日之后* 發(fā)現(xiàn)他生效了* 1991年開始了* 緊接著要注意pig2* 他也變成了1991年* 那這個就很神奇了* 我們看一下代碼* 克隆完之后* 拿到一個pig2* 他們兩是不同的對象* 那我們只設(shè)置了pig1的birthday* pig2也修改了* 這個就和我們預(yù)期就不一樣了* 那我們debug來看一下* pig1和pig2我們點開* 我們可以看到這兩個對象* 一個是426* 一個是427* 但是那里面的生日對象呢* 都是425* 也就是說這里面克隆出來的date* 引用的呢是同一個對象* 也就是我們修改一個生日對象的時候呢* 克隆出來的對象呢* 這個生日也會發(fā)生變化的* 這個就很清晰了* 那默認我們現(xiàn)在的實現(xiàn)方式呢* 又是淺克隆* 也就是在pig這一層* 只克隆當前這個層次* 如果要深克隆的話* 怎么做呢* 對于這個對象的引用類型* 生日我們也要寫一下* 他的克隆實現(xiàn)* 那很簡單* 我們直接在克隆方法里面這么寫* 我們繼續(xù)debug一下* 我們再看一下* 一個是426* 一個是427* 那發(fā)現(xiàn)里面生日這個對象呢* 也變成了425* 克隆出來的變成521* 那說明他們兩并沒有引用同一個對象* 那下面的輸出呢也符合我們的預(yù)期了* F8直接看一下* 輸出結(jié)果console* 前兩個不看了* 看后兩個* 他們兩是不一樣的* 我們只修改了pig1的生日* 1991年* 那pig2還是1970年* 這段呢非常好理解* 這個非常重要* 那原型模式簡單但是有坑* 所以我們在使用的時候* 一定要注意深克隆和淺克隆* 對于這種引用類型* 一定要注意是否需要深克隆他* 那建議還是克隆出阿里為好* 否則是給這個項目在埋坑* 希望通過以上的例子* 能更好的吸收理解原型模式* * * */System.out.println(pig1);System.out.println(pig2);// HungrySingleton hungrySingleton = HungrySingleton.getInstance(); // Method method = hungrySingleton.getClass().getDeclaredMethod("clone"); // method.setAccessible(true); // HungrySingleton cloneHungrySingleton = (HungrySingleton) method.invoke(hungrySingleton); // System.out.println(hungrySingleton); // System.out.println(cloneHungrySingleton);} }

?

超強干貨來襲 云風(fēng)專訪:近40年碼齡,通宵達旦的技術(shù)人生

總結(jié)

以上是生活随笔為你收集整理的原型模式codeing的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。