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
  • 前言 在我們開發過程中基本上不可或缺的用到一些敏感機密數據,比如SQL伺服器的連接串或者是OAuth2的Secret等,這些敏感數據在代碼中是不太安全的,我們不應該在源代碼中存儲密碼和其他的敏感數據,一種推薦的方式是通過Asp.Net Core的機密管理器。 機密管理器 在 ASP.NET Core ...
  • 新改進提供的Taurus Rpc 功能,可以簡化微服務間的調用,同時可以不用再手動輸出模塊名稱,或調用路徑,包括負載均衡,這一切,由框架實現並提供了。新的Taurus Rpc 功能,將使得服務間的調用,更加輕鬆、簡約、高效。 ...
  • 順序棧的介面程式 目錄順序棧的介面程式頭文件創建順序棧入棧出棧利用棧將10進位轉16進位數驗證 頭文件 #include <stdio.h> #include <stdbool.h> #include <stdlib.h> 創建順序棧 // 指的是順序棧中的元素的數據類型,用戶可以根據需要進行修改 ...
  • 前言 整理這個官方翻譯的系列,原因是網上大部分的 tomcat 版本比較舊,此版本為 v11 最新的版本。 開源項目 從零手寫實現 tomcat minicat 別稱【嗅虎】心有猛虎,輕嗅薔薇。 系列文章 web server apache tomcat11-01-官方文檔入門介紹 web serv ...
  • C總結與剖析:關鍵字篇 -- <<C語言深度解剖>> 目錄C總結與剖析:關鍵字篇 -- <<C語言深度解剖>>程式的本質:二進位文件變數1.變數:記憶體上的某個位置開闢的空間2.變數的初始化3.為什麼要有變數4.局部變數與全局變數5.變數的大小由類型決定6.任何一個變數,記憶體賦值都是從低地址開始往高地 ...
  • 如果讓你來做一個有狀態流式應用的故障恢復,你會如何來做呢? 單機和多機會遇到什麼不同的問題? Flink Checkpoint 是做什麼用的?原理是什麼? ...
  • C++ 多級繼承 多級繼承是一種面向對象編程(OOP)特性,允許一個類從多個基類繼承屬性和方法。它使代碼更易於組織和維護,並促進代碼重用。 多級繼承的語法 在 C++ 中,使用 : 符號來指定繼承關係。多級繼承的語法如下: class DerivedClass : public BaseClass1 ...
  • 前言 什麼是SpringCloud? Spring Cloud 是一系列框架的有序集合,它利用 Spring Boot 的開發便利性簡化了分散式系統的開發,比如服務註冊、服務發現、網關、路由、鏈路追蹤等。Spring Cloud 並不是重覆造輪子,而是將市面上開發得比較好的模塊集成進去,進行封裝,從 ...
  • class_template 類模板和函數模板的定義和使用類似,我們已經進行了介紹。有時,有兩個或多個類,其功能是相同的,僅僅是數據類型不同。類模板用於實現類所需數據的類型參數化 template<class NameType, class AgeType> class Person { publi ...
  • 目錄system v IPC簡介共用記憶體需要用到的函數介面shmget函數--獲取對象IDshmat函數--獲得映射空間shmctl函數--釋放資源共用記憶體實現思路註意 system v IPC簡介 消息隊列、共用記憶體和信號量統稱為system v IPC(進程間通信機制),V是羅馬數字5,是UNI ...