java設計模式4——原型模式

来源:https://www.cnblogs.com/xgp123/archive/2020/02/14/12306531.html
-Advertisement-
Play Games

1、原型模式介紹 2、深拷貝 3、淺拷貝 4、弊端分析 5、示例代碼演示 6、改進方案 ...


java設計模式4——原型模式

1、寫在前面

本節內容與C++語言的複製構造函數、淺拷貝、深拷貝極為相似,因此建議學習者可以先瞭解C++的該部分的相關知識,或者學習完本節內容後,也去瞭解C++的相應內容,進行比對學習。

2、原型模式介紹

原型模式(Prototype Pattern)是用於創建重覆的對象,同時又能保證性能。這種類型的設計模式屬於創建型模式,它提供了一種創建對象的最佳方式。

這種模式是實現了一個原型介面,該介面用於創建當前對象的克隆。當直接創建對象的代價比較大時,則採用這種模式。例如,一個對象需要在一個高代價的資料庫操作之後被創建。我們可以緩存該對象,在下一個請求時返回它的克隆,在需要的時候更新資料庫,以此來減少資料庫調用。

3、java實現克隆的核心

1、實現一個介面(Cloneable)

2、重寫一個方法(clone())

clone()方法的源碼分析

protected native Object clone() throws CloneNotSupportedException;

由方法聲明的放回值類型=>native,可知該方法實際上是一個C++封裝好的方法,由java來進行調用,相當於C++語言的複製構造函數,但是又有所區別。

4、第一種原型模式實現(淺拷貝)

4.1、建立視頻的原型類

package com.xgp.company.創建型模式.第四種_原型模式.demo1;

import java.util.Date;

/**
 * 1、實現一個介面
 * 2、重寫一個方法
 */
//視頻原型類
public class Video implements Cloneable {
    private String name;
    private Date createTime;

    /**
     * 重寫克隆方法
     * @return
     * @throws CloneNotSupportedException
     */
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

    public Video() {

    }

    public Video(String name, Date createTime) {
        this.name = name;
        this.createTime = createTime;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Date getCreateTime() {
        return createTime;
    }

    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }

    @Override
    public String toString() {
        return "Video{" +
                "name='" + name + '\'' +
                ", createTime=" + createTime +
                '}';
    }
}

4.2、建立複製的客戶端類

package com.xgp.company.創建型模式.第四種_原型模式.demo1;

import java.util.Date;

/**
 * 客戶端:克隆
 */
public class Client {

    public static void main(String[] args) throws CloneNotSupportedException {
        //原型對象
        Video v1 = new Video("狂神說java", new Date());
        System.out.println("v1 = " + v1);
        System.out.println("v1 = " + v1.hashCode());

        System.out.println("========================");
        //v1 克隆 v2
        Video v2 = (Video) v1.clone();
        System.out.println("v2 = " + v2);
        System.out.println("v2 = " + v2.hashCode());

    }
}

運行結果:

v1 = Video{name='狂神說java', createTime=Fri Feb 14 10:26:57 CST 2020}
v1 = 1836019240
========================
v2 = Video{name='狂神說java', createTime=Fri Feb 14 10:26:57 CST 2020}
v2 = 325040804

5、弊端

5.1、揭露弊端的代碼

/**
 * 演示淺克隆弊端
 * @param args
 * @throws CloneNotSupportedException
 */
public static void main(String[] args) throws CloneNotSupportedException {
    //原型對象
    Date date = new Date();
    Video v1 = new Video("狂神說java", date);
    System.out.println("v1 = " + v1);
    System.out.println("v1 = " + v1.hashCode());

    //v1 克隆 v2
    Video v2 = (Video) v1.clone();
    System.out.println("v2 = " + v2);
    System.out.println("v2 = " + v2.hashCode());

    System.out.println("========================");

    date.setTime(22222222);
    System.out.println("v1 = " + v1);
    System.out.println("v1 = " + v1.hashCode());

    //v1 克隆 v2
    System.out.println("v2 = " + v2);
    System.out.println("v2 = " + v2.hashCode());

}

5.2、弊端代碼的運行結果

v1 = Video{name='狂神說java', createTime=Fri Feb 14 10:29:02 CST 2020}
v1 = 1836019240
v2 = Video{name='狂神說java', createTime=Fri Feb 14 10:29:02 CST 2020}
v2 = 325040804
========================
v1 = Video{name='狂神說java', createTime=Thu Jan 01 14:10:22 CST 1970}
v1 = 1836019240
v2 = Video{name='狂神說java', createTime=Thu Jan 01 14:10:22 CST 1970}
v2 = 325040804

5.3、弊端分析

從運行結果可以看出,當改變一個被v1,v2都引用的時間對象時,兩者都發生了改變,沒有將引用的對象進行複製,因此稱之為淺拷貝。

5.4、模型圖如下:

通過上面的模型圖可以看到,被引用的對象還是只有一份,因此存在很大的弊端。在C++中,如果存在這種引用關閉,當程式員兩次刪除對象時,會出現第二次刪對象時發生異常的情況。雖然在java語言中,有著gc機制,不需要程式員手動的去釋放對象,不會出現重覆刪除的錯誤。但是,當被引用的對象發生改變時,很有可能會發生數據上的不正確。

6、改進(深拷貝模式)

6.1、我們期望想要改進後的模型圖如下:被引用的對象也複製了一份,互不幹擾。

6.2、實現方式:改造重寫的克隆方法

@Override
protected Object clone() throws CloneNotSupportedException {
    /**
     * 改造克隆方法,進行生克隆
     */
    Object obj = super.clone();
    Video v = (Video) obj;

    //將對象的屬性進行克隆
    v.createTime = (Date) this.createTime.clone();
    return obj;
}

6.3、此時的運行結果為:

v1 = Video{name='狂神說java', createTime=Fri Feb 14 10:37:33 CST 2020}
v1 = 1836019240
v2 = Video{name='狂神說java', createTime=Fri Feb 14 10:37:33 CST 2020}
v2 = 325040804
========================
v1 = Video{name='狂神說java', createTime=Thu Jan 01 14:10:22 CST 1970}
v1 = 1836019240
v2 = Video{name='狂神說java', createTime=Fri Feb 14 10:37:33 CST 2020}
v2 = 325040804

6.4、當原型引用的對像改變時,複製的對象並不發生改變,被引用的對象被覆制了兩份,因此稱之為深拷貝。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 對象的遍歷 對象可以當做數組處理,使用for in var person={}; person.name="cyy"; person.age=25; person.infos=function(){ alert(this.name+" "+this.age); } for(var i in pers ...
  • 前次用 electron-packager 打包成功,這次改用 electron-builder 打包,然後根據項目中實際需要進行選擇使用。 第一步:全局安裝 electron-builder,便於系統通用 npm install -g electron-builder 或 cnpm install ...
  • CSS 字體屬性定義文本的字體系列、大小、加粗、風格(如斜體)和變形(如小型大寫字母)font-family控制字體,由於各個電腦系統安裝的字體不盡相同,但是基本裝有黑體、宋體與微軟雅黑這三款字體,通常這樣寫font-family:"黑體", "宋體","Microsoft YaHei" font-... ...
  • jQuery初學者筆記 一 Mirror王宇陽 by jQuery語法 jQuery語法是通過選取HTML元素,並對選取的元素進行操作 基礎語法: 所有jQuery語句用“$”符號開始 jQuery函數位於一個document ready函數中,我們需要在js中載入該函數文檔 選擇器語法: jQue ...
  • JavaScript中的基本數據類型 在JS中,有6種基本數據類型: 1. string 2. number 3. boolean 4. null 5. undefined 6. Symbol(ES6) 除去這六種基本數據類型以外,其他的所有變數數據類型都是Object。基本類型的操作在JS底層中是 ...
  • 一、Overview angular 入坑記錄的筆記第一篇,完成開發環境的搭建,以及如何通過 angular cli 來創建第一個 angular 應用。入坑一個多星期,通過學習官方文檔以及手摸手的按教程敲官方的快速上手項目,很像後端,嗯,完美的契合了我這種後端開發人員。 對應官方文檔地址: 搭建本 ...
  • [1]介紹 [2]優勢 [3]安裝 [4]使用 [5]cask [6]逸事 ...
  • 簡單工廠模式 為什麼要有工程模式? 因為在有很多對象需要集中集中操作的時候,可以減少代碼的復用和提高代碼的靈活性,具體參考下例。 什麼是工廠模式? 1、什麼是工廠? 一個專門來創建實例的類叫做工廠,下麵是一個簡單的例子。 工廠模式的好處有哪些? 提高代碼服用性和靈活性,工廠模式解決了對象創建問題。 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...