天天看點

深入淺出設計模式——原型模式(Prototype Pattern)

模式動機

深入淺出設計模式——原型模式(Prototype Pattern)

在面向對象系統中,使用原型模式來複制一個對象自身,進而克隆出多個與原型對象一模一樣的對象。

在軟體系統中,有些對象的建立過程較為複雜,而且有時候需要頻繁建立,原型模式通過給出一個原型對象來指明所要建立的對象的類型,然後用複制這個原型對象的辦法建立出更多同類型的對象,這就是原型模式的意圖所在。

模式定義

原型模式(Prototype Pattern):原型模式是一種對象建立型模式,用原型執行個體指定建立對象的種類,并且通過複制這些原型建立新的對象。原型模式允許一個對象再建立另外一個可定制的對象,無須知道任何建立的細節。

原型模式的基本工作原理是通過将一個原型對象傳給那個要發動建立的對象,這個要發動建立的對象通過請求原型對象拷貝原型自己來實作建立過程。

Prototype Pattern: Specify the kind of objects to create using a prototypical instance, and create new objects by copying this prototype.

Frequency of use: medium

UML圖

深入淺出設計模式——原型模式(Prototype Pattern)

模式結構

原型模式包含如下角色:

Prototype:抽象原型類

ConcretePrototype:具體原型類

Client:客戶類

分析

通常情況下,一個類包含一些成員對象,在使用原型模式克隆對象時,根據其成員對象是否也克隆,原型模式可以分為兩種形式:深克隆和淺克隆。

淺複制:被複制的對象的所有變量都含有與原來的對象相同的值,而所有的對其他對象的引用都仍然指向原來的對象。

深複制:把引用對象的變量指向複制過的新對象,而不是原有的被引用的對象。

示例:資料集對象DataSet,它就有Clone()方法和Copy()方法,Clone()方法用來複制DataSet的結構,但不複制DataSet的資料,實作了原型模式的淺複制。Copy()方法不但複制結構,也複制資料,其實就是實作了原型模式的深複制。

模式執行個體與解析

履歷的淺複制實作

體系結構

深入淺出設計模式——原型模式(Prototype Pattern)

Resume.cs

深入淺出設計模式——原型模式(Prototype Pattern)

用戶端代碼

深入淺出設計模式——原型模式(Prototype Pattern)

履歷的深複制實作

體系結構

深入淺出設計模式——原型模式(Prototype Pattern)

WorkExperience.cs

using System;

namespace PrototypePattern
{
    class WorkExperience : ICloneable
    {
        private string workDate;
        public string WorkDate
        {
            get { return workDate; }
            set { workDate = value; }
        }
        private string company;
        public string Company
        {
            get { return company; }
            set { company = value; }
        }
        public Object Clone()
        {
            return (Object)this.MemberwiseClone();
        }
    }
}      

Resume.cs

using System;

namespace PrototypePattern
{
    class Resume : ICloneable
    {
        private string name;
        private string sex;
        private string age;   
        private WorkExperience work;
        public Resume(string name)
        {
            this.name = name;
            work = new WorkExperience();
        }
        private Resume(WorkExperience work)
        {
            //提供Clone方法調用的私有構造函數,以便克隆“工作經曆”的資料
            this.work = (WorkExperience)work.Clone();
        }
        public void SetPersonalInfo(string sex, string age)
        {
            this.sex = sex;
            this.age = age;
        }
        public void SetWorkExperience(string workDate, string company)
        {
            work.WorkDate = workDate;
            work.Company = company;
        }
        public void Display()
        {
            Console.WriteLine("{0} {1} {2}", name, sex, age);
            Console.WriteLine("工作經曆:{0} {1}", work.WorkDate, work.Company);
        }
        public Object Clone()
        {
            Resume obj = new Resume(this.work);
            obj.name = this.name;
            obj.sex = this.sex;
            obj.age = this.age;
            return obj;
        }
    }
}      

用戶端代碼

using System;

namespace PrototypePattern
{
    class Program
    {
        static void Main(string[] args)
        {
            Resume a = new Resume("張三");
            a.SetPersonalInfo("男", "29");
            a.SetWorkExperience("1998-2000", "XX公司");
            //隻需要調用Clone方法就可以實作新履歷的生成,并且再修改新履歷的細節
            Resume b = (Resume)a.Clone();
            b.SetWorkExperience("1996-2006", "YY公司");

            Resume c = (Resume)a.Clone();
            c.SetPersonalInfo("男", "24");

            a.Display();
            b.Display();
            c.Display();
            Console.Read();
        }
    }
}      

原型模式的優點

當建立新的對象執行個體較為複雜時,使用原型模式可以簡化對象的建立過程,通過一個已有執行個體可以提高新執行個體的建立效率。

可以動态增加或減少産品類。

原型模式提供了簡化的建立結構。

可以使用深克隆的方式儲存對象的狀态。

原型模式的缺點

需要為每一個類配備一個克隆方法,而且這個克隆方法需要對類的功能進行通盤考慮,這對全新的類來說不是很難,但對已有的類進行改造時,不一定是件容易的事,必須修改其源代碼,違背了“開閉原則”。

在實作深克隆時需要編寫較為複雜的代碼。

模式适用環境

在以下情況下可以使用原型模式:

 建立新對象成本較大,新的對象可以通過原型模式對已有對象進行複制來獲得,如果是相似對象,則可以對其屬性稍作修改。

 如果系統要儲存對象的狀态,而對象的狀态變化很小,或者對象本身占記憶體不大的時候,也可以使用原型模式配合備忘錄模式來應用。相反,如果對象的狀态變化很大,或者對象占用的記憶體很大,那麼采用狀态模式會比原型模式更好。

 需要避免使用分層次的工廠類來建立分層次的對象,并且類的執行個體對象隻有一個或很少的幾個組合狀态,通過複制原型對象得到新執行個體可能比使用構造函數建立一個新執行個體更加友善。

轉載于:https://www.cnblogs.com/Bobby0322/p/4184284.html

繼續閱讀