設計模式之原型模式

設計模式之原型模式

Intro 簡介

原型模式,用原型實例指定創建對象的種類,并且通過拷貝這些原型創建新的對象

原型模式其實就是從一個對象再創建另外一個可定制的對象而且不需要知道任何創建的細節。

實現方式

實現方式大致如下:

在 c# 中可以借助 ICloneable 接口和 MemberwiseClone 方法來方便的實現原型模式,需要注意的是這個方法是淺復制,當對象內嵌套了另外一個對象的時候,尤其需要注意。

// 淺復制
public object Clone() => MemberwiseClone();

示例

簡單的簡歷,所有的字段屬性都是簡單類型

public class SimpleResume : ICloneable
{
    private string _name;
    private string _email;

    private string _timePeriod;
    private string _company;

    public void SetPersonalInfo(string name, string email)
    {
        _name = name;
        _email = email;
    }

    public void SetWorkExperience(string company, string timePeriod)
    {
        _company = company;
        _timePeriod = timePeriod;
    }

    public void Display()
    {
        Console.WriteLine($"{_name} {_email}");
        Console.WriteLine($"工作經歷:{_timePeriod} {_company}");
    }

    public object Clone() => MemberwiseClone();
}

var resume = new SimpleResume();
resume.SetPersonalInfo("小明", "xiaoming@abc.xyz");
resume.SetWorkExperience("xxx公司", "1990~2000");
resume.Display();
var resume1 = (SimpleResume)resume.Clone();
resume1.SetWorkExperience("xxx企業", "1998~1999");
resume1.Display();
var resume2 = (SimpleResume)resume.Clone();
resume2.SetPersonalInfo("xiaohong", "xiaohong@abc.xyz");
resume2.Display();

深復制示例,下面是一個復雜一些的簡歷,里面包含了一個 WorkExperience 是另外一個類型,直接淺復制的話_workExperience 仍然指向原來的引用,來看下面的示例是怎么解決這個問題的

public class WorkExperience : ICloneable
{
    public string TimePeriod { get; set; }
    public string Company { get; set; }

    public object Clone() => MemberwiseClone();
}

public class ComplexResume : ICloneable
{
    private readonly WorkExperience _workExperience;
    private string _name;
    private string _email;

    public ComplexResume() => _workExperience = new WorkExperience();

    private ComplexResume(WorkExperience workExperience) => _workExperience = (WorkExperience)workExperience.Clone();

    public void SetPersonalInfo(string name, string email)
    {
        _name = name;
        _email = email;
    }

    public void SetWorkExperience(string comapny, string timePeriod)
    {
        _workExperience.Company = comapny;
        _workExperience.TimePeriod = timePeriod;
    }

    public void Show()
    {
        Console.WriteLine($"{_name} {_email}");
        Console.WriteLine($"Work Experience: {_workExperience.Company} {_workExperience.TimePeriod}");
    }

    public object Clone() => new ComplexResume(_workExperience)
    {
        _name = _name,
        _email = _email
    };
}

#region deep copy

var complexResume = new ComplexResume();
complexResume.SetPersonalInfo("xiaoming", "xiaoming@abc.xyz");
complexResume.SetWorkExperience("xiaomingTecch", "2001~2005");
complexResume.Show();

var complexResume1 = (ComplexResume)complexResume.Clone();
complexResume1.SetPersonalInfo("xiaohong", "xiaohong@abc.xyz");
complexResume1.Show();

#endregion deep copy

More

有人一定會說序列化了,當然,你用序列化也是可以做到的,序列化再反序列化得到的也是一個全新的對象,但是對于簡單的對象,我覺得用上面這種方式就足夠了,而且這種方式是直接操作內存,把對應的數據內存復制一份更加高效

我們之前搞的推送服務里有一個推送請求的對象,會頻繁的使用序列化反序列化來復制一個新的對象,這個場景就很適合使用原型模式來進行處理,高效的創建一個新的對象。

在需要頻繁的復制對象的場景下,都可以考慮使用原型模式來創建新的對象

Reference

posted @ 2020-07-17 22:58  WeihanLi  閱讀(...)  評論(...編輯  收藏
最新chease0ldman老人