Prototype Pattern的四個要素:

  1. 模式名稱

Prototype Pattern(原型模式)

  1. 問題

當需要建立多個具有相同或類似屬性的物件時,使用傳統的建立方式可能會導致程式碼重複和效率低下。

  1. 解決方案

Prototype Pattern透過使用已有的物件來複製建立新物件,從而避免了程式碼重複和效率低下的問題。

  1. 結果

使用Prototype Pattern可以更加靈活地建立和管理物件,並且可以提高程式碼的重用性和可維護性。

實作

在C#中實現原型模式,我們可以使用兩種不同的複製方式:淺層複製和深層複製。

淺層複製

淺層複製(Shallow Cpoy)是指複製物件時,只複製物件本身及其所有值類型的成員變數,而不複製物件的參考類型成員變數。這意味著複製後的物件和原始物件仍然共享參考類型成員變數,因此對複製物件或原始物件的參考類型成員變數進行修改,將會影響到另一個物件,可以透過實現ICloneable介面來實現。

public class MyClass : ICloneable
{
    public int Value;
    public List<int> List;
    public object Clone()
    {
        return MemberwiseClone();
    }
}

public class Program
{
    static void Main(string[] args)
    {
        MyClass original = new MyClass();
        original.Value = 1;
        original.List = new List<int>() { 1, 2, 3 };

        MyClass clone = (MyClass)original.Clone();
        clone.Value = 2;
        clone.List[0] = 4;

        Console.WriteLine(original.Value); // Output: 1
        Console.WriteLine(clone.Value); // Output: 2
        Console.WriteLine(original.List[0]); // Output: 4
        Console.WriteLine(clone.List[0]); // Output: 4
    }
}

在這個範例程式碼中,我們定義了一個MyClass類別,它實現了ICloneable介面並定義了Value和List成員變數。

在Main方法中,我們建立了一個original物件並設定其Value和List成員變數。然後我們透過調用Clone方法來複製這個物件並設定複製物件的Value和List成員變數。

最後,我們輸出了original和clone物件的Value和List成員變數,結果顯示出對clone物件的List成員變數進行修改同時也修改了original物件的List成員變數, 這是因為兩個物件仍然共享同一個List物件的參考

深層複製

如果希望深層複製(Deep Copy)物件,從而完全分離原始物件和複製物件。這種方式需要實現自己的Clone方法,而不是使用ICloneable介面(視情況可以使用遞迴的方式複製樹狀結構等情境)。

以下是深複製的範例程式碼:

public class MyClass
{
    public int Value;
    public List<int> List;
    public MyClass Clone()
    {
        MyClass clone = new MyClass();
        clone.Value = Value;
        clone.List = new List<int>(List);
        return clone;
    }
}

public class Program
{
    static void Main(string[] args)
    {
        MyClass original = new MyClass();
        original.Value = 1;
        original.List = new List<int>() { 1, 2, 3 };

        MyClass clone = original.Clone();
        clone.Value = 2;
        clone.List[0] = 4;

        Console.WriteLine(original.Value); // Output: 1
        Console.WriteLine(clone.Value); // Output: 2
        Console.WriteLine(original.List[0]); // Output: 1
        Console.WriteLine(clone.List[0]); // Output: 4
    }
}

在這個示例程式碼中,我們定義了一個MyClass類別,它定義了Value和List成員變數,並定義了自己的Clone方法。

在Main方法中,我們建立了一個original物件並設定其Value和List成員變數。然後我們透過調用Clone方法來複製這個物件並設定複製物件的Value和List成員變數。在複製List成員變數時,我們使用了List的複製建構子(Copy Constructor)來複製List物件本身。

最後,我們輸出了original和clone物件的Value和List成員變數,結果顯示出對clone物件的List成員變數進行修改並不會影響original物件的List成員變數,這是因為兩個物件已經完全分離。

總之,Prototype模式是一種創建型設計模式,它可以通過複製現有物件來創建新物件,從而避免直接創建物件所帶來的開銷和複雜性。要實現Prototype模式,可以使用ICloneable介面或自己的Clone方法,並分別實現Shadow Clone和Deep Clone的方式來複製物件。在C#中,可以使用ICloneable介面或自己的Clone方法來實現Prototype模式,並透過複製建構子來複製成員變數,從而實現Shadow Clone和Deep Clone的方式。