国产av日韩一区二区三区精品,成人性爱视频在线观看,国产,欧美,日韩,一区,www.成色av久久成人,2222eeee成人天堂

目錄
淺克隆 " >淺克隆
深克隆 " >深克隆
首頁 Java java教程 五分鐘 掌握 原型模式

五分鐘 掌握 原型模式

Aug 25, 2023 pm 03:52 PM
java


大家好,我是老田,今天我要跟大家分享設計模式中的原型模式 #。用貼切的生活故事,以及真實專案場景來講設計模式,最後用一句話來總結這個設計模式。

五分鐘 掌握 原型模式

故事

#還記得大四那年找工作,無意中我得從網(wǎng)路上找到一份相對漂亮的程式設計師履歷模板,然後全班同學開啟瘋狂的履歷拷貝(U盤)。同時也鬧出了一個笑話,有幾位同學,拷貝過去的履歷,內(nèi)容完全沒改,名字都沒有改,截止投給面試官(校招面試官)。後來,結果大家也應該可以猜出來,大家都去實習了,部分人還在找工作。 後面公司面試官和同伴的其他同學回饋:收到一毛一樣的履歷,好幾份,回來大家一聊就知道問題出哪裡了,承認了自己拷貝過去完全沒改就拿出去投了,害,尷尬的一匹。

把履歷拷貝分成為兩種:

  • 一種是拷貝履歷,然後把資訊修改成自己的
  • #另外一種是,拷貝履歷,內(nèi)容什麼都不改。

原型模式定義

Specify the kinds of objects to create using a prototype instance ,and create new objects by coping this prototype

大致意思:用原型實例指定創(chuàng)建物件的種類,並且透過複製這些原型創(chuàng)建新的物件。

原型模式:Prototype Pattern,屬於創(chuàng)建型模式。

呼叫者不需要知道任何建立細節(jié),也不用呼叫建構方法來建立物件。

使用場景

#原型模式有以下使用場景:

  • 類別初始化消耗資源較多
  • new產(chǎn)生的一個物件需要非常繁瑣的過程(資料準備、存取權限等)
  • 建構函數(shù)比較複雜
  • 循環(huán)體內(nèi)產(chǎn)生大量物件時
  • 在Spring中,原型模式應用的非常廣泛,例如:scope='prototype'

我們可以將一些getter和setter之類封裝成一個工廠方法,然後對於使用的人來說,呼叫方法就可以了,不需要知道裡面的getter和setter是怎麼處理的。我們也可以使用JDK提供的實作Cloneable接口,實作快速複製。

建立物件的四種方式:

new、反射、複製、序列化

實際案例

大家是否有遇過這種常見,就是專案中規(guī)定,不能把與資料庫表映射的entity類別回傳給前端,所以通?;貍鹘o前端的有各種O,例如:XxxVO、XxxBO、XxxDTO...

這時候就會出現(xiàn)下面的場景,大家也想已經(jīng)??猜到了。

下面是與資料庫表格對應的UserEntity實體類別。

public class UserEntity {
    private Long id;
    private String name;
    private Integer age;
    //....可能還有很多屬性
    //省略getter setter
}

傳回給前端或呼叫方的UserVO實體類別。

public class UserVO {
    private Long id;
    private String name;
    private Integer age;
    //....可能還有很多屬性
    //省略getter setter
}

此時,從資料庫查出來的UserEntity需要轉(zhuǎn)換成UserVO,然後再回傳給前端(或呼叫方)。

public class ObjectConvertUtil {

    public static UserVo convertUserEntityToUserVO(UserEntity userEntity) {
        if (userEntity == null) {
            return null;
        }
        UserVo userVo = new UserVo();

        userVo.setId(userEntity.getId());
        userVo.setName(userEntity.getName());
        userVo.setAge(userEntity.getAge());
         //如果還有更多屬性呢?
        return userVo;
    }
}

從這個util類中,我們可以看出,如果一個類的屬性有幾十個,上百個的,這代碼量是不是有點恐怖?

于是,我們通常都會使用一些工具類來處理,比如常見有以下:

BeanUtils.copy();
JSON.parseObject()
Guava工具類
.....

這些工具類就用到了原型模式。

通過一個對象,創(chuàng)建一個新的對象。

也把原型模式稱之為對象的拷貝、克隆。

其實對象的克隆分淺克隆和深克隆,下面我們就來聊聊淺克隆和深克隆。

  • 淺克?。簞?chuàng)建一個新對象,新對象的屬性和原來對象完全相同,對于非基本類型屬性,仍指向原來對象的屬性所指向的對象的內(nèi)存地址。
  • 深克隆:創(chuàng)建一個新對象,屬性中引用的其他對象也會被克隆,不再指向原有對象地址。

我們先來聊聊淺克隆,都喜歡由淺入深。

淺克隆

比如,我現(xiàn)在相對用戶信息User進行克隆,但是User中有用戶地址信息UserAddress屬性。

以下是代碼的實現(xiàn):

//用戶地址信息
public class UserAddress  implements Serializable{
    private String province;
    private String cityCode;

    public UserAddress(String province, String cityCode) {
        this.province = province;
        this.cityCode = cityCode;
    }
}
//用戶信息
public class User implements Cloneable {
    private int age;
    private String name;
    //用戶地址信息
    private UserAddress userAddress;

    //getter setter 省略

    @Override
    protected Object clone() throws CloneNotSupportedException { 
        return super.clone();
    }
}
//測試
public class UserTest {
    public static void main(String[] args) throws Exception {
        User user = new User();
        user.setAge(20);
        user.setName("田維常");
        UserAddress userAddress = new UserAddress("貴州", "梵凈山");
        user.setUserAddress(userAddress);

        User clone = (User) user.clone();

        System.out.println("克隆前后UserAddress比較:" + (user.getUserAddress() == clone.getUserAddress()));
    }
}

輸出結果

克隆前后 UserAddress 比較:true

兩個對象屬性 UserAddress 指向的是同一個地址。

這就是所謂的淺克隆,只是克隆了對象,對于該對象的非基本類型屬性,仍指向原來對象的屬性所指向的對象的內(nèi)存地址。

關系如下:

五分鐘 掌握 原型模式


深克隆

關于深克隆,我們來用一個很經(jīng)典的案例,西游記里的孫悟空。一個孫悟空能變成n多個孫悟空,手里都會拿著一個金箍棒。

按照前面的淺克隆,結果就是:孫悟空倒是變成很多孫悟空,但是金箍棒用的是同一根。

深克隆的結果是:孫悟空變成了很多個,金箍棒也變成很多個根。

下面我們用代碼來實現(xiàn):

//猴子,有身高體重和生日
public class Monkey {
    public int height;
    public int weight;
    public Date birthday;
}

孫悟空也是猴子,兵器 孫悟空有個金箍棒:

import java.io.Serializable;
//孫悟空的金箍棒
public class JinGuBang implements Serializable{
    public float  h=100;
    public float  d=10;
    //金箍棒變大
    public void big(){
        this.h *=10;
        this.d *=10;
    }
    //金箍棒變小
    public void small(){
        this.h /=10;
        this.d /=10;
    }
}

齊天大圣孫悟空:

import java.io.*;
import java.util.Date;

//孫悟空有七十二變,拔猴毛生成一個金箍棒
//使用JDK的克隆機制,
//實現(xiàn)Cloneable并重寫clone方法
public class QiTianDaSheng extends Monkey implements Cloneable, Serializable {

    public JinGuBang jinGuBang;

    public QiTianDaSheng() {
        this.birthday = new Date();
        this.jinGuBang = new JinGuBang();
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return this.deepClone();
    }

    //深克隆
    public QiTianDaSheng deepClone() {
        try {
            //內(nèi)存中操作完成、對象讀寫,是通過字節(jié)碼直接操作
            //與序列化操作類似
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(bos);
            oos.writeObject(this);

            ByteArrayInputStream bais = new ByteArrayInputStream(bos.toByteArray());
            ObjectInputStream bis = new ObjectInputStream(bais);

            //完成一個新的對象,底層是使用new創(chuàng)建的一個對象
            //詳情可以了解readObject方法
            QiTianDaSheng qiTianDaSheng = (QiTianDaSheng) bis.readObject();
            //每個猴子的生日不一樣,所以每次拷貝的時候,把生日改一下
            qiTianDaSheng.birthday = new Date();
            return qiTianDaSheng;
        } catch (Exception ex) {
            ex.printStackTrace();
            return null;
        }
    }

    //淺克隆,就是簡單的賦值
    public QiTianDaSheng shalllowClone(QiTianDaSheng target) {
        QiTianDaSheng qiTianDaSheng = new QiTianDaSheng();
        qiTianDaSheng.height = target.height;
        qiTianDaSheng.weight = target.weight;

        qiTianDaSheng.jinGuBang = target.jinGuBang;
        qiTianDaSheng.birthday = new Date();
        return qiTianDaSheng;

    }
}

接著我們就來測試一下:

public class DeepCloneTest {
    public static void main(String[] args) {
        QiTianDaSheng qiTianDaSheng = new QiTianDaSheng();
        try {
            QiTianDaSheng newObject = (QiTianDaSheng) qiTianDaSheng.clone();
            System.out.print("深克隆后 ");
            System.out.println("金箍棒是否一直:" + (qiTianDaSheng.jinGuBang == newObject.jinGuBang));
            
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        
        QiTianDaSheng newObject=qiTianDaSheng.shalllowClone(qiTianDaSheng);
        System.out.print("淺克隆后 ");
        System.out.println("金箍棒是否一直:" + (qiTianDaSheng.jinGuBang == newObject.jinGuBang));
    }
}

輸出結果為:

深克隆后 金箍棒是否一直:false
淺克隆后 金箍棒是否一直:true

結論

深克隆后每個孫悟空都有自己的金箍棒,而淺克隆后每個孫悟空用的金箍棒實質(zhì)上還是同一根。

五分鐘 掌握 原型模式

總結

切記:深和淺,指的是克隆對象里的屬性(引用類型)是否指向同一個內(nèi)存地址。

為了更深刻的理解深克隆和淺克隆,我們回答文中的簡歷拷貝的故事。

  • 深拷貝:拷貝一份履歷,然後將履歷中的資訊進行修改成自己的
  • 淺拷貝:拷貝一份履歷,履歷內(nèi)容完全不變

優(yōu)點:

  • #Java 原型模式基於記憶體二進位流複製,比直接new 的效能會更好一些。
  • 可以利用深克隆保存物件狀態(tài),存一份舊的(克隆出來),在對其修改,可以充當一個撤銷功能。

缺點:

  • #需要設定clone 方法,改造時需要對已有類別進行修改,違背「開閉原則」。
  • 如果物件間存在多重巢狀參考時,每一層都需要實作複製。

我們從原型模式的定義,使用場景,真實案例、淺克隆、深克隆、優(yōu)缺點等方面,對原型模式進行了一個全面的講解。

#

以上是五分鐘 掌握 原型模式的詳細內(nèi)容。更多資訊請關注PHP中文網(wǎng)其他相關文章!

本網(wǎng)站聲明
本文內(nèi)容由網(wǎng)友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發(fā)現(xiàn)涉嫌抄襲或侵權的內(nèi)容,請聯(lián)絡admin@php.cn

熱AI工具

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅(qū)動的應用程序,用於創(chuàng)建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發(fā)環(huán)境

Dreamweaver CS6

Dreamweaver CS6

視覺化網(wǎng)頁開發(fā)工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

Laravel 教程
1600
29
PHP教程
1501
276
如何使用JDBC處理Java的交易? 如何使用JDBC處理Java的交易? Aug 02, 2025 pm 12:29 PM

要正確處理JDBC事務,必須先關閉自動提交模式,再執(zhí)行多個操作,最後根據(jù)結果提交或回滾;1.調(diào)用conn.setAutoCommit(false)以開始事務;2.執(zhí)行多個SQL操作,如INSERT和UPDATE;3.若所有操作成功則調(diào)用conn.commit(),若發(fā)生異常則調(diào)用conn.rollback()確保數(shù)據(jù)一致性;同時應使用try-with-resources管理資源,妥善處理異常並關閉連接,避免連接洩漏;此外建議使用連接池、設置保存點實現(xiàn)部分回滾,並保持事務盡可能短以提升性能。

了解Java虛擬機(JVM)內(nèi)部 了解Java虛擬機(JVM)內(nèi)部 Aug 01, 2025 am 06:31 AM

TheJVMenablesJava’s"writeonce,runanywhere"capabilitybyexecutingbytecodethroughfourmaincomponents:1.TheClassLoaderSubsystemloads,links,andinitializes.classfilesusingbootstrap,extension,andapplicationclassloaders,ensuringsecureandlazyclassloa

如何使用Java的日曆? 如何使用Java的日曆? Aug 02, 2025 am 02:38 AM

使用java.time包中的類替代舊的Date和Calendar類;2.通過LocalDate、LocalDateTime和LocalTime獲取當前日期時間;3.使用of()方法創(chuàng)建特定日期時間;4.利用plus/minus方法不可變地增減時間;5.使用ZonedDateTime和ZoneId處理時區(qū);6.通過DateTimeFormatter格式化和解析日期字符串;7.必要時通過Instant與舊日期類型兼容;現(xiàn)代Java中日期處理應優(yōu)先使用java.timeAPI,它提供了清晰、不可變且線

比較Java框架:Spring Boot vs Quarkus vs Micronaut 比較Java框架:Spring Boot vs Quarkus vs Micronaut Aug 04, 2025 pm 12:48 PM

前形式攝取,quarkusandmicronautleaddueTocile timeProcessingandGraalvSupport,withquarkusoftenpernperforminglightbetterine nosserless notelless centarios.2。

垃圾收集如何在Java工作? 垃圾收集如何在Java工作? Aug 02, 2025 pm 01:55 PM

Java的垃圾回收(GC)是自動管理內(nèi)存的機制,通過回收不可達對象釋放堆內(nèi)存,減少內(nèi)存洩漏風險。 1.GC從根對象(如棧變量、活動線程、靜態(tài)字段等)出發(fā)判斷對象可達性,無法到達的對像被標記為垃圾。 2.基於標記-清除算法,標記所有可達對象,清除未標記對象。 3.採用分代收集策略:新生代(Eden、S0、S1)頻繁執(zhí)行MinorGC;老年代執(zhí)行較少但耗時較長的MajorGC;Metaspace存儲類元數(shù)據(jù)。 4.JVM提供多種GC器:SerialGC適用於小型應用;ParallelGC提升吞吐量;CMS降

了解網(wǎng)絡端口和防火牆 了解網(wǎng)絡端口和防火牆 Aug 01, 2025 am 06:40 AM

NetworkPortSandFireWallsworkTogetHertoEnableCommunication whereSeringSecurity.1.NetWorkPortSareVirtualendPointSnumbered0-655 35,with-Well-with-Newonportslike80(HTTP),443(https),22(SSH)和25(smtp)sindiessingspefificservices.2.portsoperateervertcp(可靠,c

以身作則,解釋說明 以身作則,解釋說明 Aug 02, 2025 am 06:26 AM

defer用於在函數(shù)返回前執(zhí)行指定操作,如清理資源;參數(shù)在defer時立即求值,函數(shù)按後進先出(LIFO)順序執(zhí)行;1.多個defer按聲明逆序執(zhí)行;2.常用於文件關閉等安全清理;3.可修改命名返回值;4.即使發(fā)生panic也會執(zhí)行,適合用於recover;5.避免在循環(huán)中濫用defer,防止資源洩漏;正確使用可提升代碼安全性和可讀性。

比較Java構建工具:Maven vs. Gradle 比較Java構建工具:Maven vs. Gradle Aug 03, 2025 pm 01:36 PM

Gradleisthebetterchoiceformostnewprojectsduetoitssuperiorflexibility,performance,andmoderntoolingsupport.1.Gradle’sGroovy/KotlinDSLismoreconciseandexpressivethanMaven’sverboseXML.2.GradleoutperformsMaveninbuildspeedwithincrementalcompilation,buildcac

See all articles