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

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

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、當原型引用的對像改變時,複製的對象並不發生改變,被引用的對象被覆制了兩份,因此稱之為深拷貝。


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

更多相關文章
  • 對象的遍歷 對象可以當做數組處理,使用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、什麼是工廠? 一個專門來創建實例的類叫做工廠,下麵是一個簡單的例子。 工廠模式的好處有哪些? 提高代碼服用性和靈活性,工廠模式解決了對象創建問題。 ...
一周排行
  • 最近由於疫情緊張,遂在家辦公,在領導的帶領下,學習了一下.Net Core MVC。 一,構建web應用 1.選擇c#-所有平臺-web 找到ASP.NET Core web應用程式 2.項目命名之後轉至如下界面:選擇Web應用程式(模型視圖控制器)。 Ok點擊創建,這個項目的基本框架就生成了。 二 ...
  • 本筆記摘抄自:https://www.cnblogs.com/PatrickLiu/p/7792973.html,記錄一下學習過程以備後續查用。 一、引言 今天我們要講結構型設計模式的第六個模式--享元模式,先從名字上來看,“享元”可以這樣理解--共用“單元”。單元是什麼呢?舉例說明:對於圖形而言就 ...
  • 本筆記摘抄自:https://www.cnblogs.com/PatrickLiu/p/7814004.html,記錄一下學習過程以備後續查用。 一、引言 今天我們要講結構型設計模式的第七個模式,也是結構型設計模式中的最後一個模式--代理模式。先從名字上來看,“代理”可以理解為“代替”,代替“主人” ...
  • 本筆記摘抄自:https://www.cnblogs.com/PatrickLiu/p/7837716.html,記錄一下學習過程以備後續查用。 一、引言 今天我們要講行為型設計模式的第一個模式--模板方法模式,先從名字上來看。“模板方法”理解為有一個方法的名字叫“模板方法”,也可以換個理解方法: ...
  • 本筆記摘抄自:https://www.cnblogs.com/PatrickLiu/p/7873322.html,記錄一下學習過程以備後續查用。 一、引言 今天我們要講行為型設計模式的第二個模式--命令模式,又稱為行動(Action)模式或交易(Transaction)模式,先從名字上來看。“命令模 ...
  • 前面幾章介紹了處理適量適中的圖形內容的最佳方法。通過使用幾何圖形、圖畫和路徑,可以降低2D圖形的開銷。即使正在使用複雜的具有分層效果的組合形狀和漸變畫刷,這種方法也仍然能夠正常得很好。 然而,這樣設計不適合需要渲染大量圖形元素的繪圖密集型應用程式。例如繪圖程式、演示粒子碰撞的物理模型程式或橫向卷軸形 ...
  • Dubbo的服務暴露是一個重要的特性,瞭解其機制很重要。之前有很多人寫了有關的源代碼分析,在本文中不再重新分析。官方文檔中的一篇寫的就很好,本文主要是有關內容進行補充與總結。 傳送門: "服務導出" 為什麼要服務暴露 服務暴露分為遠程暴露和本地暴露。在遠程服務暴露中會將服務信息上傳到註冊中心。這時客 ...
  • 在上一篇文章 Dubbo之服務暴露分析 中介紹了當遠程暴露時,如果有註冊中心,需要在服務暴露後再將服務註冊到註冊中心。該篇將介紹該功能的有關步驟。 註冊的起點 在 方法包含了服務導出,註冊,以及數據訂閱等邏輯。其中服務註冊先調用 方法。 可以看出,服務註冊主要包括兩部分, 獲取註冊中心實例 和 向註 ...
  • 從今天開始,將會逐步介紹關於DUbbo的有關知識。首先先簡單介紹一下DUbbo的整體概述。 概述 Dubbo是SOA(面向服務架構)服務治理方案的核心框架。用於分散式調用,其重點在於分散式的治理。 簡單的來說,可以把它分為四個角色。服務提供方(Provider)、服務消費方(Consumer)、註冊 ...
  • [TOC] python是數據分析的主要工具,它包含的數據結構和數據處理工具的設計讓python在數據分析領域變得十分快捷。它以NumPy為基礎,並對於需要類似 for迴圈 的大量數據處理的問題有非常快捷的數組處理函數。 但是pandas最擅長的領域還是在處理表格型二維以上不同數據類型數據。 基本導 ...
x