06_原型模式

野码發表於2024-03-09

原型模式是一種建立型設計模式,它透過克隆現有物件來建立新物件,而不是透過例項化類來建立。原型模式允許我們建立具有相同屬性和方法的物件集合,從而減少了物件的建立成本。

在原型模式中,我們首先建立一個原始物件,然後透過克隆該物件來建立新的物件。這樣,我們可以在不重新例項化類的情況下建立多個相似的物件。

原型模式適用於以下場景:

  1. 當一個系統需要建立大量相似物件時,使用原型模式可以提高效能。

  2. 當物件的建立成本比克隆成本高時,使用原型模式可以節省資源。

  3. 當一個物件需要配置大量屬性時,使用原型模式可以簡化物件的建立過程。

總結而言,原型模式透過克隆現有物件來建立新物件,減少了物件的建立成本,提高了系統的效能和效率。

/// <summary>
    /// 電池
    /// </summary>
    [Serializable]
    public class Battery
    {
        /// <summary>
        /// 容量
        /// </summary>
        public int Capacity { get; set; } = 0;
        /// <summary>
        /// 電壓
        /// </summary>
        public double Voltage { get; set; } = 0;
        /// <summary>
        /// 功率
        /// </summary>
        public double Power { get; set; } = 0;
    }

手機物件介面

public interface IPhone
    {
        /// <summary>
        /// CPU
        /// </summary>
        string CPU { get; set; }
        /// <summary>
        /// 記憶體
        /// </summary>
        int Memory { get; set; }
        /// <summary>
        /// 電池
        /// </summary>
        Battery Battery { get; set; }

        void Write(string tag);
        /// <summary>
        /// 淺複製
        /// </summary>
        /// <returns></returns>
        IPhone Clone();
        /// <summary>
        /// 深複製
        /// </summary>
        /// <returns></returns>
        IPhone DeepClone();
    }

/// <summary>
    /// 序列化幫助類
    /// </summary>
    public class SerializableHelper
    {
        /// <summary>
        /// 序列化
        /// </summary>
        /// <param name="target"></param>
        /// <returns></returns>
        public string Serializable(object target)
        {
            using(MemoryStream stream= new MemoryStream())
            {
                new BinaryFormatter().Serialize(stream, target);
                return Convert.ToBase64String(stream.ToArray());
            }
        }

        /// <summary>
        /// 反序列化
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="target"></param>
        /// <returns></returns>
        public T Derializable<T>(string target)
        {
            return (T)Derializable(target);
        }

        public object Derializable(string target)
        {
            byte[] array = Convert.FromBase64String(target);
            using(MemoryStream stream = new MemoryStream(array))
            {
                return new BinaryFormatter().Deserialize(stream);
            }
        }
    }

/// <summary>
    /// 蘋果手機類
    /// </summary>
    [Serializable]
    public class ApplePhone : IPhone
    {
        public ApplePhone()
        {
            Battery = new Battery
            {
                Capacity = 5000,
                Power = 5,
                Voltage = 3.7
            };
        }
        /// <summary>
        /// CPU
        /// </summary>
        public string CPU { get; set; } = string.Empty;
        /// <summary>
        /// 記憶體
        /// </summary>
        public int Memory { get; set; } = 0;
        /// <summary>
        /// 電池
        /// </summary>
        public Battery Battery { get; set; }

        /// <summary>
        /// 淺克隆
        /// </summary>
        /// <returns></returns>
        public IPhone Clone()
        {
            return this.MemberwiseClone() as ApplePhone;
        }

        /// <summary>
        /// 深克隆
        /// </summary>
        /// <returns></returns>
        public IPhone DeepClone()
        {
            SerializableHelper helper = new SerializableHelper();
            string target = helper.Serializable(this);
            return helper.Derializable<IPhone>(target);
        }

        public void Write(string tag)
        {
            Console.WriteLine($"{tag}=> CPU = {CPU},Memory = {Memory}");
        }
    }

淺克隆
在淺克隆中,如果原型物件的成員變數是值型別,將複製一份給新物件,如果是引用型別,在淺克隆中會複製一份引用型別的引用給新物件,也就是說新物件和原型物件的引用變數指向相同的記憶體地址。簡單來說,淺克隆只會複製變數中直接儲存的內容。

深克隆
深克隆中,如果原型物件的成員變數是值型別,將複製一份給新物件,如果是引用型別,深克隆會將引用變數指向記憶體區域中儲存的實際資料複製一份給新物件,這時新物件的所有操作都不會對原型物件產生影響,真正意義上的全新的物件。

呼叫

public class Client
    {
        public void Start()
        {
            IPhone iphone1 = new ApplePhone();
            iphone1.CPU = "最初的三星S5L8900";
            iphone1.Memory = 1;
            iphone1.Write("iphone1");
            Console.WriteLine($"iphone1.Battery.Capacity={iphone1.Battery.Capacity} maA");

            IPhone iphone15 = iphone1.Clone();//淺複製
            iphone15.Write("iphone15");
            Console.WriteLine($"iphone15.Battery.Capacity={iphone15.Battery.Capacity} maA");

            //修改iphone15物件的內容
            iphone15.CPU = "晶片:A16仿生晶片,16核神經引擎,5核GPU、6核CPU";
            iphone15.Memory = 512;
            iphone15.Battery.Capacity++;

            iphone15.Write("iphone15修改後");
            iphone1.Write("iphone1");

            Console.WriteLine($"iphone15.Battery.Capacity={iphone15.Battery.Capacity} maA");
            Console.WriteLine($"iphone1.Battery.Capacity={iphone1.Battery.Capacity} maA");

            Console.WriteLine("---------------------漂亮的分割線------------------------");

            IPhone iphone16 = iphone1.DeepClone();//深複製
            iphone16.Write("iphone16");
            Console.WriteLine($"iphone16.Battery.Capacity={iphone16.Battery.Capacity} maA");

            iphone16.CPU = "12核CPU,10核GPU";
            iphone16.Memory = 1024;
            iphone16.Battery.Capacity++;

            iphone16.Write("iphone16修改後");
            iphone1.Write("iphone1");
            Console.WriteLine($"iphone16.Battery.Capacity={iphone16.Battery.Capacity} maA");
            Console.WriteLine($"iphone1.Battery.Capacity={iphone1.Battery.Capacity} maA");



        }
    }

static void Main(string[] args)
        {
            new Client().Start();

            Console.ReadKey();
        }

相關文章