1. 程式人生 > >大話設計模式-原型模式

大話設計模式-原型模式

原型模式

用原型例項指定建立物件的種類,並且通過拷貝這些原型建立新的物件。

原型模式其實就是從一個物件再建立另外一個可定製的物件,而且不需要知道任何建立的細節。

 


原型模式結構演示

原型抽象類:Prototype

abstract class Prototype{
    public string Id { get; set; }
    public Prototype(string id) => Id = id;
    public abstract Prototype Clone();
}

具體原型類:ConcretePrototype1

class ConcretePrototype1 : Prototype{
    public ConcretePrototype1(string id) : base(id){ }
    public override Prototype Clone() => (Prototype)this.MemberwiseClone();
}

測試類:Program

ConcretePrototype1 p1 = new ConcretePrototype1("A");
ConcretePrototype1 c1 = (ConcretePrototype1)p1.Clone();
Console.WriteLine(
"Cloned:"+c1.Id); //結果 Cloned:A

對於.NET而言,原型抽象類Prototypr使用不到的,因為克隆很常用,.NET在System名稱空間提供了ICloneable介面,其中一個方法就是Clone(),只需要實現這個介面就可以完成原型克隆了。

 


簡歷的原型實現

簡歷類:Resume

class Resume : ICloneable{
    private string name, sex, age, timeArea, company;
    public Resume(string name) => this.name = name;
    
public void SetPersonalInfo(string sex, string age){ this.sex = sex; this.age = age; } public void SetWorkExperience(string timeArea,string company){ this.timeArea = timeArea; this.company = company; } public void Display(){ Console.WriteLine($"{name},{sex},{age}"); Console.WriteLine($"工作經歷:{timeArea},{company}"); } public object Clone() => MemberwiseClone(); }

測試類:Program

//簡歷a
Resume a = new Resume("曹丞相");
a.SetPersonalInfo("","29");
a.SetWorkExperience("2017-2018", "網易公司");
//簡歷b,修改工作經歷
Resume b = (Resume)a.Clone();
b.SetWorkExperience("2018-2019", "騰訊公司");
//簡歷c,修改年齡
Resume c = (Resume)a.Clone();
c.SetPersonalInfo("", "30");
//顯示
a.Display();
b.Display();
c.Display();
//測試結果
曹丞相,男,29
工作經歷:2017-2018,網易公司
曹丞相,男,29
工作經歷:2018-2019,騰訊公司
曹丞相,男,30
工作經歷:2017-2018,網易公司

 


淺複製與深複製

MemberwiseClone()方法是這樣的,如果欄位是值型別就對該欄位執行逐位複製,如果欄位是引用型別,則複製引用但不復制引用的物件,因此原始物件及其副本引用同一物件。即淺複製。

 


簡歷的深複製實現

工作經歷類:WorkExperience

假如增加工作經歷類,將工作時間和公司封裝到工作經歷類。

class WorkExperience : ICloneable{
    public string WorkDate { get; set; }
    public string Conpany { get; set; }
    public Object Clone() => MemberwiseClone();
}

簡歷類:Resume

修改簡歷類的欄位、構造器、設定工作經歷方法和Clone方法。

class Resume : ICloneable{
    private string name, sex, age;
    private WorkExperience work;
    //構造器
    public Resume(string name){
        this.name = name;
        work = new WorkExperience();
    }
    public Resume(WorkExperience work) => 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(
        $"{name},{sex},{age + Environment.NewLine}工作經歷:{work.WorkDate},{work.Company}"
    );
    //克隆簡歷
    public object Clone()
    {
        //呼叫私有的構造方法,讓工作經歷類克隆完成
        //再給簡歷物件的欄位複製,最終返回一個深複製的簡歷物件
        return new Resume(work){
            name = name,
            sex = sex,
            age = age
        };
    }
}