iT邦幫忙

2022 iThome 鐵人賽

DAY 21
1

今天要來介紹Prototype模式,簡單來說就是「複製」,在第19天時我們有提到說建立物件池去保存昂貴物件,那麼當我現在已經財富自由了,不用去管制購買機器的數量,只要求快點將昂貴的機器製造出來,這時候就可以使用「複製」的方式去複製昂貴物件,減少製作昂貴物件可能帶來的負擔。

我們先來介紹 淺拷貝 & 深拷貝

  • 淺拷貝(Shallow Clone) :
    1. 若物件的屬性為主要型別(Int, Boolean…等),則該屬性直接複製到新物件的屬性中。
    2. 若物件的屬性為引用型別(Class, Interface…等),則該新物件的屬性直接存取該物件屬性的參照位置。
  • 深拷貝(Deep Clone) :
    1. 不論物件屬性為主要型別或引用型別,皆直接複製至新物件屬性中,所以新物件和原物件會變成兩個對應到不同參照位置的個體,並且沒有相關的參照引用。

Prototype - 定義

用原型的實例來指定創建的對象種類,並通過複製這些原型創造新的對象。

https://ithelp.ithome.com.tw/upload/images/20220927/20136443r82woDZbUD.png

(圖片來源:https://www.dofactory.com/img/diagrams/net/prototype.png)

範例 UML

https://ithelp.ithome.com.tw/upload/images/20220927/20136443aVHVDRnuJi.png

Code要點

  • BookPrototype為抽象類別,定義ShallowClone()以及DeepClone()兩種複製方法。
  • C# 淺拷貝可以使用 MemberwiseClone() 方法。
  • DeepClone()中將 Color(引用型別)重新建置並指派,因此新物件和原物件兩個的Color就對應到不同參照位置的個體,就算有更動屬性值也不會互相影響。

不囉嗦上Code!

using System;

namespace DAY21_Prototype
{
    internal class Program
    {
        static void Main(string[] args)
        {
            // 淺拷貝
            Book BookShallow = new Book("雜誌",new Color(255, 0, 0));
            var BookShallowCopy = (Book)BookShallow.ShallowClone();
            BookShallowCopy.name = "漫畫";
            BookShallowCopy.color.green = 100;

            Console.WriteLine($"淺拷貝 | 書名:{BookShallow.name},顏色RGB:{BookShallow.color.red},{BookShallow.color.green},{BookShallow.color.blue}");
            Console.WriteLine($"淺拷貝 | 書名:{BookShallowCopy.name},顏色RGB:{BookShallowCopy.color.red},{BookShallowCopy.color.green},{BookShallowCopy.color.blue}");

            Console.WriteLine("-------------");

            // 深拷貝
            Book BookDeep = new Book("雜誌", new Color(255, 0, 0));
            var BookDeepCopy = (Book)BookDeep.DeepClone();
            BookDeepCopy.name = "漫畫";
            BookDeepCopy.color.green = 100;

            Console.WriteLine($"淺拷貝 | 書名:{BookDeep.name},顏色RGB:{BookDeep.color.red},{BookDeep.color.green},{BookDeep.color.blue}");
            Console.WriteLine($"淺拷貝 | 書名:{BookDeepCopy.name},顏色RGB:{BookDeepCopy.color.red},{BookDeepCopy.color.green},{BookDeepCopy.color.blue}");

            Console.ReadKey();
        }
    }

    public abstract class BookPrototype
    {
        public abstract BookPrototype ShallowClone();
        public abstract BookPrototype DeepClone();
    }

    public class Book : BookPrototype
    {
        public string name;
        public Color color;

        public Book(string name, Color color)
        {
            this.color = color;
            this.name = name;
        }
        public override BookPrototype ShallowClone()
        {
            // C# 淺拷貝使用 MemberwiseClone() 方法
            return (BookPrototype)this.MemberwiseClone();
        }

        public override BookPrototype DeepClone()
        {
            // C# 深拷貝,建立新 Color 物件,使指派的記憶體位置不同
            BookPrototype deepClone = (BookPrototype)this.MemberwiseClone();
            ((Book)deepClone).color = new Color(color.red, color.green, color.blue);
            return deepClone;
        }
    }

    public class Color
    {
        public int red;
        public int green;
        public int blue;
        public Color(int red, int green, int blue)
        {
            this.red = red;
            this.green = green;
            this.blue = blue;
        }
    }
}
  • 結果

https://ithelp.ithome.com.tw/upload/images/20220927/2013644391vMBOxr4i.png

簡單的小結

我們今天介紹了Prototype模式,也簡單說明了淺拷貝與深拷貝,所以就Prototype模式而言,不管我們用淺拷貝(Shallow Clone)還是深拷貝(Deep Clone)的方式來複製物件,都還是透過一個已經存在的實例來返回新的實例,而不是新建實例。因此當要製作昂貴物件時,就能夠減少成本,增加物件建構的效率。


上一篇
【DAY20】Builder模式 - 今晚...我想來點麥當勞(下)
下一篇
【DAY22】Composite模式 - 從種子到大樹的過程
系列文
勇闖秘境!探索物件導向背後的設計模式30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言