c#中原型模式詳解

来源:https://www.cnblogs.com/mingnianjiehunba/archive/2023/11/07/17721835.html
-Advertisement-
Play Games

本節介紹Util應用框架如何進行驗證. 概述 驗證是業務健壯性的基礎. .Net 提供了一套稱為 DataAnnotations 數據註解的方法,可以對屬性進行一些基本驗證,比如必填項驗證,長度驗證等. Util應用框架使用標準的數據註解作為基礎驗證,並對自定義驗證進行擴展. 基礎用法 引用Nuge ...


基礎介紹:

  具體可分為2個角色:

    Prototype(原型類):聲明一個Clone自身的介面;

    ConcretePrototype(具體原型類):,實現一個Clone自身的操作。

  在原型模式中,Prototype通常提供一個包含Clone方法的介面,具體的原型ConcretePrototype使用Clone方法完成對象的創建。

 

  本質:通過拷貝這些原型對象創建新的對象。

  根據其本質可以理解,原型本身就是通過一個自身的Clone方法來進行自我複製,從而產生新的對象。

  比如,孫猴子吹猴毛變化多個克隆體時,就是用了原型模式,通過對自身的自我複製從而生產出N個分身。

  所以從本質出發,想要實現這個功能,可以引出兩個概念:其一就是淺層複製,再則就是深層複製

  淺層複製:通過this.MemberWiseClone(),對實例的值類型進行拷貝(包含string類型),對引用類型只拷貝了引用。淺拷貝只對值類型成員進行複製,對於引用類型,只是複製了其引用,並不複製其對象。

  深層複製需要通過反射和序列化來實現。

 

應用場景:

  對象在創建(new)時,消耗資源過多繁瑣耗時。

  本質就是在對象的構造函數中有耗時長或者占用系統資源多的情況,

  使用原型模式進行複製對象時,可以省去這些耗時耗力的操作,直接獲得對象的具體實例。

  最常見的使用場景之一就是對象歷史節點的保存,比如在對對象進行操作一次後,進行一次複製保存當前狀態(恢復到某一歷史狀態),可實現撤銷操作。

創建方式:

  1. 原型類----用來規範具體原型

     1     /// <summary>
     2     /// 原型類
     3     /// </summary>
     4     public abstract class Prototype
     5     {
     6         /// <summary>
     7         /// 值類型
     8         /// </summary>
     9         public int Id { get; set; }
    10 
    11         /// <summary>
    12         /// 字元串
    13         /// </summary>
    14         public string strMessage { get; set; }
    15 
    16         /// <summary>
    17         /// 引用類型
    18         /// </summary>
    19         public Dictionary<int, string> keyValuePairs = new Dictionary<int, string>() { };
    20 
    21         /// <summary>
    22         /// 構造函數
    23         /// </summary>
    24         /// <param name="id"></param>
    25         public Prototype(int id)
    26         {
    27             this.Id = id;
    28         }
    29 
    30         /// <summary>
    31         /// 複製函數
    32         /// </summary>
    33         /// <returns></returns>
    34         public abstract Prototype Clone();
    35     }
    View Code

    通過上述代碼可以看出,為了更好的展示原型類的特性,原型類中聲明瞭值類型和引用類型來展示各自的變化。

  2. 具體原型類

     1     /// <summary>
     2     /// 創建具體原型
     3     /// </summary>
     4     public class ConcretePrototype : Prototype
     5     {
     6         public ConcretePrototype(int id)
     7             : base(id)
     8         { }
     9 
    10         /// <summary>
    11         /// 淺拷貝
    12         /// </summary>
    13         /// <returns></returns>
    14         public override Prototype Clone()
    15         {
    16             // 調用MemberwiseClone方法實現的是淺拷貝,另外還有深拷貝
    17             return (Prototype)this.MemberwiseClone();
    18         }
    19     }
    View Code

    通過MemberwiseClone方法實現淺拷貝,即複製值類型屬性生成新的,而引用類型的屬性只複製其引用,並沒有生成新的。

  3. 客戶端調用

     1     class Program
     2     {
     3         static void Main(string[] args)
     4         {
     5             ConcretePrototype concretePrototype = new ConcretePrototype(1);
     6             concretePrototype.strMessage = "AAAAAAAAA";
     7             concretePrototype.keyValuePairs.Add(1, "A");
     8             concretePrototype.keyValuePairs.Add(2, "B");
     9             Console.WriteLine("id:{0}", concretePrototype.Id);
    10             Console.WriteLine("strMessage:{0}", concretePrototype.strMessage);
    11             Console.WriteLine("keyValuePairs:");
    12             foreach (KeyValuePair<int,string> item in concretePrototype.keyValuePairs)
    13             {
    14                 Console.WriteLine("KEY:{0}  Value:{1}", item.Key, item.Value);
    15             }
    16 
    17             Console.WriteLine("\r\n");
    18 
    19             ConcretePrototype concretePrototype2 = (ConcretePrototype)concretePrototype.Clone();
    20             concretePrototype2.strMessage = "BBBBBBBBB";
    21             concretePrototype2.keyValuePairs[1] = "A1";
    22             Console.WriteLine("id:{0}", concretePrototype2.Id);
    23             Console.WriteLine("strMessage:{0}", concretePrototype2.strMessage);
    24             Console.WriteLine("keyValuePairs:");
    25             foreach (KeyValuePair<int, string> item in concretePrototype2.keyValuePairs)
    26             {
    27                 Console.WriteLine("KEY:{0}  Value:{1}", item.Key, item.Value);
    28             }
    29 
    30             Console.WriteLine("\r\n");
    31 
    32             Console.WriteLine("id:{0}", concretePrototype.Id);
    33             Console.WriteLine("strMessage:{0}", concretePrototype.strMessage);
    34             Console.WriteLine("keyValuePairs:");
    35             foreach (KeyValuePair<int, string> item in concretePrototype.keyValuePairs)
    36             {
    37                 Console.WriteLine("KEY:{0}  Value:{1}", item.Key, item.Value);
    38             }
    39             Console.ReadKey();
    40         }
    41     }
    View Code

    上述代碼中,首先創建了一個concretePrototype原型對象,然後給字元串類型的strMessage賦值“AAAAAAAAA”。 然後給引用類型的keyValuePairs字典添加key=1和key=2,值分別是A和B。

    通過Clone()方法進行原型對象的複製操作,生成新對象concretePrototype2。

    修改新對象中的strMessage屬性和keyValuePairs字典中key=1的值為“A1”。

    通過列印出的內容可以看出新對象中的strMessage值修改並不會影響原型對象中的內容,而引用類型keyValuePairs則發生了改變。

    通過這個實例可以看出淺複製,對值類型進行全盤拷貝,對引用類型只拷貝了引用地址。

  4. 修改上述實例,將淺複製改為深複製

     1     /// <summary>
     2     /// 原型類
     3     /// </summary>
     4     [Serializable]
     5     public abstract class Prototype
     6     {
     7         ......
     8     }    
     9 
    10         /// <summary>
    11     /// 創建具體原型
    12     /// 如果是要通過序列化來進行深拷貝的話,要打上Serializable標簽
    13     /// </summary>
    14     [Serializable]
    15     public class ConcretePrototype : Prototype
    16     {
    17         public ConcretePrototype(int id)
    18             : base(id)
    19         { }
    20 
    21         /// <summary>
    22         /// 深拷貝
    23         /// </summary>
    24         /// <returns>返回一個全新的Person對象</returns>
    25         public override Prototype Clone()
    26         {
    27             //創建一個記憶體流
    28             MemoryStream ms = new MemoryStream();
    29             //創建一個二進位序列化對象
    30             BinaryFormatter bf = new BinaryFormatter();
    31             //將當前對象序列化寫入ms記憶體流中
    32             bf.Serialize(ms, this);
    33             //設置流讀取的位置
    34             ms.Position = 0;
    35             //將流反序列化為Object對象
    36             return bf.Deserialize(ms) as Prototype;
    37         }
    38     }
    View Code

    上述實例通過序列化進行深複製,當然也可以使用反射等技術進行深複製。

    運行後可以看出,深複製後引用類型也會生成一個新的地址。

總結:

  原型模式就是對對象進行複製操作,而避免重覆進行初始化操作,生產多個克隆對象。

  

  

作者:少年真愛 出處:https://www.cnblogs.com/mingnianjiehunba/p/17721835.html 博主的文章沒有高度、深度和廣度,只是湊字數。由於博主的水平不高,不足和錯誤之處在所難免,希望大家能夠批評指出。 博主是利用讀書、參考、引用、抄襲、複製和粘貼等多種方式打造成自己的文章,請原諒博主成為一個無恥的文檔搬運工!
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一、創建string對象 var strOb = new String("abcefg"); var strOb = String("abcefg"); var strOb = "abcefg"; 二、屬性 length (字元串長度) var str = 'hello'; console.log( ...
  • 這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 前言 在學習Grid佈局之時,我發現其是CSS中的一種強大的佈局方案,它將網頁劃分成一個個網格,可以任意組合不同的網格,做出各種各樣的佈局,在刷某書和某寶首頁時,我們發現其展示方式就是一種瀑布流,是一種流行的網站頁面佈局,視覺表現為參差不 ...
  • 隨著項目的發展,前端SPA應用的規模不斷加大、業務代碼耦合、編譯慢,導致日常的維護難度日益增加。同時前端技術的發展迅猛,導致功能擴展吃力,重構成本高,穩定性低。為了能夠將前端模塊解耦,通過相關技術調研,最終選擇了無界微前端框架作為物流客服系統解耦支持。為了更好的使用無界微前端框架,我們對其運行機制進... ...
  • 引言 前端性能已成為網站和應用成功的關鍵要素之一。用戶期望快速載入的頁面和流暢的交互,而前端框架的選擇對於實現這些目標至關重要。然而,傳統的前端框架在某些情況下可能面臨性能挑戰且存在技術壁壘。 在這個充滿挑戰的背景下,我們引入了 Qwik.js 框架。Qwik.js 不僅是一個前端框架,更是一種前端 ...
  • 本篇文章將解決上一篇文章 結尾遺留的問題:如何讓代碼自動實現響應性? 換句話說就是,如何讓我們的 effect 自動保存 & 自動重新運行?又如何攔截對象屬性的訪問和賦值操作? ...
  • 從接觸領域驅動設計的初學階段,到實現一個舊系統改造到DDD模型,再到按DDD規範落地的3個的項目。對於領域驅動模型設計研發,從開始的各種疑惑到吸收各種先進的理念,目前在技術實施這一塊已經基本比較成熟。在既往經驗中總結了一些在開發中遇到的技術問題和解決方案進行分享。 ...
  • 一、定義 運用共用技術有效地支持大量細粒度對象的復用,享元模式是一種結構型模式。 二、描述 享元模式要求能夠共用的對象必須是細粒度對象,因此它又稱為輕量級模式。享元模式的結構較為複雜,一般結合工廠模式一起使用,在其結構圖中包含了一個享元工廠類,包含以下四個角色: 1、Flyweight(抽象享元類) ...
  • 哈嘍大家好,我是鹹魚 想必大家都聽說過 Instagram ,它是全球最受歡迎的社交媒體平臺之一,擁有數十億的活躍用戶 Instagram 誕生於 2010 年,上線一周就坐擁 10 萬註冊用戶,一年之內就擁有了 1400 萬用戶,可見擴張趨勢突飛猛進。 Instagram 誕生的時候只有 3 個工 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...