Prototype Pattern —— Creational Class

来源:https://www.cnblogs.com/mysticbinary/archive/2023/08/30/17666450.html
-Advertisement-
Play Games

# Background knowledge 在Java中,Cloneable 介面是一個標記介面(Marker Interface,它們內部都沒有方法和屬性),實現Cloneable介面表示該對象能被克隆,能使用Object.clone()方法。 要實現克隆功能,需要滿足以下兩個條件: - 類實現 ...


Background knowledge

在Java中,Cloneable 介面是一個標記介面(Marker Interface,它們內部都沒有方法和屬性),實現Cloneable介面表示該對象能被克隆,能使用Object.clone()方法。

要實現克隆功能,需要滿足以下兩個條件:

  • 類實現了 Cloneable 介面。
  • 在類中重寫 clone() 方法。

What is Prototype Pattern

原型模式通過複製現有對象來創建新對象,而無需顯式地使用構造函數。原型模式允許動態創建對象,並且可以避免創建子類的複雜性。原型模式可以結合其他設計模式使用,例如工廠方法模式,以便更靈活地創建對象。

這個複製分為兩種模式:

  • 深複製
    深克隆(Deep Clone),深克隆是指創建一個新對象,並將原始對象的所有成員變數(無論是值類型還是引用類型)的值都複製到新對象中,包括引用類型成員變數所引用的對象。這樣,新對象和原始對象將擁有彼此獨立的成員變數副本,彼此之間的修改不會相互影響。深克隆涉及到遞歸地複製對象及其引用對象的過程,因此可能會比較複雜和耗時。
    一般考慮使用深克隆,就是因為有可變的引用類型會受影響, 既然引用類型無法被完全克隆,那麼我們可以考慮在引用類型所在的類也實現Cloneable介面。有多少個引用類型,就去實現多少個Cloneable介面。

  • 淺複製
    淺克隆(Shallow Clone),淺克隆是指創建一個新對象,並將原始對象的非引用類型成員變數的值複製到新對象中。對於引用類型成員變數,淺克隆將複製引用,使新對象和原始對象共用相同的引用對象。這意味著在淺克隆後,如果修改其中一個對象的引用類型成員變數,將會影響到另一個對象。因此,淺克隆只複製對象的錶面結構,而不涉及引用對象本身的複製。

    淺拷貝的情況下,原被克隆對象發生變化後,克隆對象的基本數據類型不可變引用數據類型(String)的數據不會發生影響,而一些其他欄位為可變的應用類型,只要克隆對象的內容隨著被克隆對象的變化發生了同樣的變化,說明兩個對象的屬性欄位指向同一個引用,才會造成這樣的結局。(我就碰到過因為對象被同事插進來的代碼導致對象發生了變更,代碼出現BUG的問題,後面是使用的深拷貝才消除同事的代碼對該對象的影響)。

    如果克隆的對象內沒有可變的引用對象,都是只用使用一些基礎類型,那麼直接用淺拷貝即可。

配合其他設計模式:
原型模式可以結合其他設計模式使用,例如工廠方法模式,以便更靈活地創建對象。

Key elements

  • 抽象原型類
  • 具體實現類
  • Client

Example of Draw shape —— shallow clone

以下是一個簡單的淺克隆例子。

抽象原型類:

abstract class Shape implements Cloneable {
    protected String type;

    abstract void draw();

    @Override
    public Object clone() {
        Object clone = null;
        try {
            clone = super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return clone;
    }
}

具體實現類:

// 具體原型類 - Rectangle
class Rectangle extends Shape {
    public Rectangle() {
        this.type = "Rectangle";
    }

    public void draw() {
        System.out.println("Drawing a rectangle.");
    }
}

// 具體原型類 - Circle
class Circle extends Shape {
    public Circle() {
        this.type = "Circle";
    }

    public void draw() {
        System.out.println("Drawing a circle.");
    }
}

Client:

// 客戶端代碼
public class Main {
    public static void main(String[] args) {
        Shape rectangle = new Rectangle();
        Shape circle = new Circle();

        Shape clonedRectangle = (Shape) rectangle.clone();
        Shape clonedCircle = (Shape) circle.clone();

        System.out.println("Original Rectangle Type: " + rectangle.type);
        rectangle.draw(); // Drawing a rectangle.
        System.out.println("Cloned Rectangle Type: " + clonedRectangle.type);
        clonedRectangle.draw(); // Drawing a rectangle.

        System.out.println("Original Circle Type: " + circle.type);
        circle.draw(); // Drawing a circle.
        System.out.println("Cloned Circle Type: " + clonedCircle.type);
        clonedCircle.draw(); // Drawing a circle.
    }
}

在上面的示例中,我們定義了抽象原型類 Shape,它包含了 clone() 方法和 draw() 方法。然後,我們實現了具體的原型類 Rectangle 和 Circle,它們繼承自 Shape 並實現了相應的方法。

在客戶端代碼中,我們首先創建了一個原始的 Rectangle 對象和一個原始的 Circle 對象。然後,我們分別對它們進行克隆,並得到克隆後的 Shape 對象。

通過原型模式,我們可以通過克隆(淺克隆)現有對象來創建新對象,而無需顯式地調用構造函數。這消除了重覆創建相似對象的需要,並提高了性能。

Reference

深克隆請參考這個文章
https://cloud.tencent.com/developer/article/1628044


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

-Advertisement-
Play Games
更多相關文章
  • 前言 前面說了很多Kafka的性能優點,有些童鞋要說了,這Kafka在企業開發或者企業級應用中要怎麼用呢?今天咱們就來簡單探究一下。 1、 使用 Kafka 進行消息的非同步處理 Kafka 提供了一個可靠的消息傳遞機制,使得企業能夠將不同組件之間的通信解耦,實現高效的非同步處理。在企業級應用中,可以通 ...
  • ## 2023年8月23日 ### #include `cstdio` 有兩個函數 printf,scanf 用於輸出和輸入 ```txt int : %d float : %f double : %lf char : %c long long : %lld ``` `iostream` 有 cin ...
  • 1. 獲取當前目錄下所有文件名 import os def get_all_files(directory): file_list = [] # os.walk返回一個生成器,每次迭代時返回當前目錄路徑、子目錄列表和文件列表 for root, dirs, files in os.walk(dire ...
  • 數組用於在單個變數中存儲相同類型的多個值,而不是為每個值聲明單獨的變數。 聲明數組 在Go中,有兩種聲明數組的方式: 1. 使用`var`關鍵字: 語法 `var array_name = [length]datatype{values} // 這裡定義了長度` 或者 `var array_name ...
  • # 各個數據類型的內置方法 ## 整形和浮點型的內置方法 ```python # 1、定義: # 1.1 整型int的定義 age=10 # 本質age = int(10) # 1.2 浮點型float的定義 salary=3000.3 # 本質salary=float(3000.3) # 註意:名 ...
  • # 引言 * 引用是C++的特性,指針是C語言的特性 * 關於這兩種特性的運行效率,人云亦云,好多人都說引用傳遞效率更高 * 以至於一些面試官在自己都不清楚的前提下麵試別人 * 筆者有幸遇到過,由於看過底層彙編,在面試官對我說引用效率更高的時候,導致我一度懷疑自己的記憶力 * 下麵我們就看看引用在匯 ...
  • # Core 建造者模式又稱為`生成器模式`,主要用於對複雜對象的構建、初始化,它可以將多個簡單的組件對象按順序一步步組裝起來,最終構建成一個複雜的成品對象。 與工廠系列模式不同的是,建造者模式的主要目的在於把煩瑣的**構建過程**從不同對象中抽離出來,使其脫離並獨立於產品類與工廠類,最終實現**用 ...
  • 本文是區塊鏈瀏覽器系列的第五篇,項目完整代碼在[這裡](https://github.com/mengbin92/browser/tree/main)。 在[上一篇文章](https://mengbin.top/2023-08-20-browser2/)中給瀏覽器增加了簡單的用戶認證,至此瀏覽器的基 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...