JAVA設計模式之原型模式(prototype)

来源:https://www.cnblogs.com/sx-bj-srr/archive/2020/05/23/prototype.html
-Advertisement-
Play Games

原型模式: 原型模式又叫克隆模式 Java自帶克隆模式 實現克隆模式必須實現Cloneable 介面,如果不實現會發生java.lang.CloneNotSupportedException異常 當某個類的屬性已經設定好需要創建很多相同屬性值的對象的時候使用clone模式非常方便 使用clone模式 ...


原型模式:

  • 原型模式又叫克隆模式
  • Java自帶克隆模式
  • 實現克隆模式必須實現Cloneable
  • 介面,如果不實現會發生java.lang.CloneNotSupportedException異常
  • 當某個類的屬性已經設定好需要創建很多相同屬性值的對象的時候使用clone模式非常方便
  • 使用clone模式不見得比傳統的new方式性能高
  • 淺克隆和深克隆

先看下麵的代碼,沒有實現Cloneable介面

package com.srr.dp.clone;

/**
 * (原型模式)克隆模式
 */
public class Appler /*implements Cloneable*/{

    private String clor;
    private int weight;
    private int volume;
    private StringBuilder descr;

    public Appler(String clor) {
        this.clor = clor;
    }

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

    @Override
    public String toString() {
        return "Appler{" +
                "clor='" + clor + '\'' +
                ", weight=" + weight +
                ", volume=" + volume +
                ", descr=" + descr +
                '}';
    }
}

package com.srr.dp.clone;

public class T {
    public static void main(String[] args) throws CloneNotSupportedException {

        Appler appler = new Appler("yellow");

        Appler appler1 = (Appler) appler.clone();

        System.out.println(appler1);
    }
}

運行結果:

 

淺拷貝:

package com.srr.dp.clone;

/**
 * (原型模式)克隆模式
 *  淺拷貝
 */
public class Appler implements Cloneable {

    private String clor;
    private int weight;
    private int volume;
    private Location loc;

    public Appler(String clor,int weight,int volume,Location loc) {
        this.clor = clor;
        this.weight = weight;
        this.volume = volume;
        this.loc = loc;
    }
    public String getClor() {
        return clor;
    }

    public void setClor(String clor) {
        this.clor = clor;
    }

    public int getWeight() {
        return weight;
    }

    public void setWeight(int weight) {
        this.weight = weight;
    }

    public int getVolume() {
        return volume;
    }

    public void setVolume(int volume) {
        this.volume = volume;
    }

    public Location getLoc() {
        return loc;
    }

    public void setLoc(Location loc) {
        this.loc = loc;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        //loc = (Locaton) loc.clone();
        return super.clone();
    }

    @Override
    public String toString() {
        return "Appler{" +
                "clor='" + clor + '\'' +
                ", weight=" + weight +
                ", volume=" + volume +
                ", loc=" + loc +
                '}';
    }
}

package com.srr.dp.clone;

public class Location {
    String name;
    public Location(String name){
        this.name = name;
    }

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

package com.srr.dp.clone;

/**
 * 測試代碼
 */
public class T {
    public static void main(String[] args) throws CloneNotSupportedException {
        Appler appler = new Appler("yellow",1,1,new Location("洛川"));
        Appler appler1 = (Appler) appler.clone();
        appler.setClor("red");
        appler.getLoc().name = "寶雞";
        System.out.println("appler1 = "+appler1);
        System.out.println("appler = "+appler);
    }
}

運行結果:

 

從結果發現,當改變appler 的顏色還有location的值後,拷貝的apper1對象的顏色未發生改變但是location發生了改變。

這就是淺拷貝,引用對象無法保證拷貝之後完全獨立只是拷貝了地址但是地址指向的對象是共用的,

雖然String類型也是引用類型但是共用常量池所以不會有這個問題。

那麼如何讓引用類型拷貝之後獨立呢?

那麼就要使用深拷貝請看如下代碼:

package com.srr.dp.clone;

/**
 * (原型模式)克隆模式
 *  淺拷貝
 */
public class Appler implements Cloneable {

    private String clor;
    private int weight;
    private int volume;
    private Location loc;

    public Appler(String clor,int weight,int volume,Location loc) {
        this.clor = clor;
        this.weight = weight;
        this.volume = volume;
        this.loc = loc;
    }
    public String getClor() {
        return clor;
    }

    public void setClor(String clor) {
        this.clor = clor;
    }

    public int getWeight() {
        return weight;
    }

    public void setWeight(int weight) {
        this.weight = weight;
    }

    public int getVolume() {
        return volume;
    }

    public void setVolume(int volume) {
        this.volume = volume;
    }

    public Location getLoc() {
        return loc;
    }

    public void setLoc(Location loc) {
        this.loc = loc;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        Appler appler = (Appler)super.clone();
        appler.loc = (Location) loc.clone();;
        return appler;
    }

    @Override
    public String toString() {
        return "Appler{" +
                "clor='" + clor + '\'' +
                ", weight=" + weight +
                ", volume=" + volume +
                ", loc=" + loc +
                '}';
    }
}

package com.srr.dp.clone;

public class Location implements Cloneable{
    String name;
    public Location(String name){
        this.name = name;
    }

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

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

package com.srr.dp.clone;

/**
 * 測試代碼
 */
public class T {
    public static void main(String[] args) throws CloneNotSupportedException {
        Appler appler = new Appler("yellow",1,1,new Location("洛川"));
        Appler appler1 = (Appler) appler.clone();
        appler.setClor("red");
        appler.getLoc().name = "寶雞";
        System.out.println("appler1 = "+appler1);
        System.out.println("appler = "+appler);
    }
}

運行結果:

從結果發現,當改變appler 的顏色還有location的值後,拷貝的apper1對象的顏色未發生改變location也發生了改變。

 上面說到String類型的拷貝不存在淺拷貝的問題,那麼StringBuilder或者StringBuffer呢,鑒於篇幅這裡使用StringBuilder來舉例

請看代碼:

package com.srr.dp.clone;

/**
 * (原型模式)克隆模式
 *  淺拷貝
 */
public class Appler implements Cloneable {

    private String color;
    private int weight;
    private int volume;
    private Location loc;

    public String getColor() {
        return color;
    }

    public StringBuilder getDesc() {
        return desc;
    }

    public void setDesc(StringBuilder desc) {
        this.desc = desc;
    }

    private StringBuilder desc = new StringBuilder("好吃");

    public Appler(String color,int weight,int volume,Location loc) {
        this.color = color;
        this.weight = weight;
        this.volume = volume;
        this.loc = loc;
    }
    public String getClor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public int getWeight() {
        return weight;
    }

    public void setWeight(int weight) {
        this.weight = weight;
    }

    public int getVolume() {
        return volume;
    }

    public void setVolume(int volume) {
        this.volume = volume;
    }

    public Location getLoc() {
        return loc;
    }

    public void setLoc(Location loc) {
        this.loc = loc;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        Appler appler = (Appler)super.clone();
        appler.loc = (Location) loc.clone();
        return appler;
    }

    @Override
    public String toString() {
        return "Appler{" +
                "color='" + color + '\'' +
                ", weight=" + weight +
                ", volume=" + volume +
                ", loc=" + loc +
                ", desc=" + desc +
                '}';
    }
}

package com.srr.dp.clone;

public class Location implements Cloneable{
    String name;
    public Location(String name){
        this.name = name;
    }

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

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

package com.srr.dp.clone;

/**
 * 測試代碼
 */
public class T {
    public static void main(String[] args) throws CloneNotSupportedException {
        Appler appler = new Appler("yellow",1,1,new Location("洛川"));
        Appler appler1 = (Appler) appler.clone();
        appler.getDesc().append("得不得了");
        appler.getLoc().name = "寶雞";
        System.out.println("appler1 = "+appler1);
        System.out.println("appler = "+appler);
    }
}

運行結果:

 

 這是是後你會發現當appler的desc值發生改變之後,apper1的值也發生改變了,說明StringBuilder的拷貝方式為淺拷貝,那麼如何實現深拷貝呢

請看代碼:

package com.srr.dp.clone;

/**
 * (原型模式)克隆模式
 *  淺拷貝
 */
public class Appler implements Cloneable {

    private String color;
    private int weight;
    private int volume;
    private Location loc;

    public String getColor() {
        return color;
    }

    public StringBuilder getDesc() {
        return desc;
    }

    public void setDesc(StringBuilder desc) {
        this.desc = desc;
    }

    private StringBuilder desc = new StringBuilder("好吃");

    public Appler(String color,int weight,int volume,Location loc) {
        this.color = color;
        this.weight = weight;
        this.volume = volume;
        this.loc = loc;
    }
    public String getClor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public int getWeight() {
        return weight;
    }

    public void setWeight(int weight) {
        this.weight = weight;
    }

    public int getVolume() {
        return volume;
    }

    public void setVolume(int volume) {
        this.volume = volume;
    }

    public Location getLoc() {
        return loc;
    }

    public void setLoc(Location loc) {
        this.loc = loc;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        Appler appler = (Appler)super.clone();
        appler.loc = (Location) loc.clone();
        appler.desc = new StringBuilder(this.desc);
        return appler;
    }

    @Override
    public String toString() {
        return "Appler{" +
                "color='" + color + '\'' +
                ", weight=" + weight +
                ", volume=" + volume +
                ", loc=" + loc +
                ", desc=" + desc +
                '}';
    }
}

package com.srr.dp.clone;

public class Location implements Cloneable{
    String name;
    public Location(String name){
        this.name = name;
    }

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

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

package com.srr.dp.clone;

/**
 * 測試代碼
 */
public class T {
    public static void main(String[] args) throws CloneNotSupportedException {
        Appler appler = new Appler("yellow",1,1,new Location("洛川"));
        Appler appler1 = (Appler) appler.clone();
        appler.getDesc().append("得不得了");
        appler.getLoc().name = "寶雞";
        System.out.println("appler1 = "+appler1);
        System.out.println("appler = "+appler);
    }
}

運行結果:

 

這是是後你會發現當appler的desc值發生改變之後,apper1的值並沒有發生改變。

寫到這裡原型模式就介紹完了。

原創不易,請多多支持!


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

-Advertisement-
Play Games
更多相關文章
  • 表單一點擊提交按鈕(submit)必然跳轉頁面,如果表單的action為空也會跳轉到自己的頁面,即效果為刷新當前頁。 如下,可以看到一點擊提交按鈕,瀏覽器的刷新按鈕閃了一下: 如果想要阻止表單的預設提交事件,有以下幾種方法: 1.將<input>標簽內按鈕類型從type="submit"修改為typ ...
  • 什麼是前端? 前端即網站前臺部分,也叫前端開發,運行在PC端,移動端等瀏覽器上展現給用戶瀏覽的網頁。隨著互聯網的發展,HTML5,CSS3,前端框架的應用,跨平臺響應式網頁設計能夠適應各種屏幕解析度,完美的動效設計,給用戶帶來極高的用戶體驗。 (核心技術:HTML、CSS、JavaScript) 核 ...
  • 前言 從最開始的小公司做小網站,到現在進入現在的公司做項目,發現小公司里很多很多工作都是重覆的勞動(增刪改查),不過想想也是,業務軟體最基礎的東西不就是增刪改查嗎。 但是很多時候,這種業務邏輯其實沒有必要挨個重寫。總不能說你的增刪改查比我的高級很多。很大程度上,複雜的問題只是數據太多了怎麼優化。 簡 ...
  • 解釋器是一種不常使用的設計模式,它用於描述如何構成一個簡單的語言解釋器,主要應用於使用面向對象語言開發的編譯器和解釋器設計。當我們需要開發一個新的語言時,可以考慮使用解釋器模式 模式動機 如果在系統中某一特定類型的問題發生的頻率很高,此時可以考慮將這些問題的實例表述為一個語言中的句子。再構建一個解釋 ...
  • 使用請註明出處 整理不易 ...
  • 在入正題之前我們再回顧下它的架構圖: 本文章主要分析AMP各索引的作用,與及結合1.7環境上已接入的服務數據對比後,對索引中的主要欄位進行解析。文章分為四個小章節。 1、索引類型 apm索引分為四種類型: 系統指標索引(System status metrics),索引名稱格式:apm-versio ...
  • 集合(set)是一個無序的不重覆元素序列。 可以使用大括弧 { } 或者 set() 函數創建集合,註意:創建一個空集合必須用 set() 而不是 { },因為 { } 是用來創建一個空字典。 創建格式:list_1 = {value01,value02,...} 或者 set(value) 集合作 ...
  • 文件的操作包含:讀、寫、修改 文件的多種操作: 1 # 讀取文件的所有內容 2 data = open("yesteday.txt", encoding="utf-8") .read() 3 print(data) 4 5 ''' f:文件句柄(包含這個文件的文件名,字元集,大小,在硬碟中的起始位置 ...
一周排行
    -Advertisement-
    Play Games
  • GoF之工廠模式 @目錄GoF之工廠模式每博一文案1. 簡單說明“23種設計模式”1.2 介紹工廠模式的三種形態1.3 簡單工廠模式(靜態工廠模式)1.3.1 簡單工廠模式的優缺點:1.4 工廠方法模式1.4.1 工廠方法模式的優缺點:1.5 抽象工廠模式1.6 抽象工廠模式的優缺點:2. 總結:3 ...
  • 新改進提供的Taurus Rpc 功能,可以簡化微服務間的調用,同時可以不用再手動輸出模塊名稱,或調用路徑,包括負載均衡,這一切,由框架實現並提供了。新的Taurus Rpc 功能,將使得服務間的調用,更加輕鬆、簡約、高效。 ...
  • 本章將和大家分享ES的數據同步方案和ES集群相關知識。廢話不多說,下麵我們直接進入主題。 一、ES數據同步 1、數據同步問題 Elasticsearch中的酒店數據來自於mysql資料庫,因此mysql數據發生改變時,Elasticsearch也必須跟著改變,這個就是Elasticsearch與my ...
  • 引言 在我們之前的文章中介紹過使用Bogus生成模擬測試數據,今天來講解一下功能更加強大自動生成測試數據的工具的庫"AutoFixture"。 什麼是AutoFixture? AutoFixture 是一個針對 .NET 的開源庫,旨在最大程度地減少單元測試中的“安排(Arrange)”階段,以提高 ...
  • 經過前面幾個部分學習,相信學過的同學已經能夠掌握 .NET Emit 這種中間語言,並能使得它來編寫一些應用,以提高程式的性能。隨著 IL 指令篇的結束,本系列也已經接近尾聲,在這接近結束的最後,會提供幾個可供直接使用的示例,以供大伙分析或使用在項目中。 ...
  • 當從不同來源導入Excel數據時,可能存在重覆的記錄。為了確保數據的準確性,通常需要刪除這些重覆的行。手動查找並刪除可能會非常耗費時間,而通過編程腳本則可以實現在短時間內處理大量數據。本文將提供一個使用C# 快速查找並刪除Excel重覆項的免費解決方案。 以下是實現步驟: 1. 首先安裝免費.NET ...
  • C++ 異常處理 C++ 異常處理機制允許程式在運行時處理錯誤或意外情況。它提供了捕獲和處理錯誤的一種結構化方式,使程式更加健壯和可靠。 異常處理的基本概念: 異常: 程式在運行時發生的錯誤或意外情況。 拋出異常: 使用 throw 關鍵字將異常傳遞給調用堆棧。 捕獲異常: 使用 try-catch ...
  • 優秀且經驗豐富的Java開發人員的特征之一是對API的廣泛瞭解,包括JDK和第三方庫。 我花了很多時間來學習API,尤其是在閱讀了Effective Java 3rd Edition之後 ,Joshua Bloch建議在Java 3rd Edition中使用現有的API進行開發,而不是為常見的東西編 ...
  • 框架 · 使用laravel框架,原因:tp的框架路由和orm沒有laravel好用 · 使用強制路由,方便介面多時,分多版本,分文件夾等操作 介面 · 介面開發註意欄位類型,欄位是int,查詢成功失敗都要返回int(對接java等強類型語言方便) · 查詢介面用GET、其他用POST 代碼 · 所 ...
  • 正文 下午找企業的人去鎮上做貸後。 車上聽同事跟那個司機對罵,火星子都快出來了。司機跟那同事更熟一些,連我在內一共就三個人,同事那一手指桑罵槐給我都聽愣了。司機也是老社會人了,馬上聽出來了,為那個無辜的企業經辦人辯護,實際上是為自己辯護。 “這個事情你不能怪企業。”“但他們總不能讓銀行的人全權負責, ...