亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

深入理解Java設(shè)計(jì)模式之原型模式

 更新時(shí)間:2021年11月07日 15:04:29   作者:一指流砂~  
這篇文章主要介紹了JAVA設(shè)計(jì)模式之原型模式的的相關(guān)資料,文中示例代碼非常詳細(xì),供大家參考和學(xué)習(xí),感興趣的朋友可以了解下

一、前言

單例模式可以避免重復(fù)創(chuàng)建消耗資源的對象,但是卻不得不共用對象。若是對象本身也不讓隨意訪問修改時(shí),怎么辦?通常做法是備份到副本,其它對象操作副本,最后獲取權(quán)限合并,類似git上的PR操作。

二、什么是原型模式

原型模式用原型實(shí)例指定創(chuàng)建對象的種類,并通過拷貝這些原型創(chuàng)建新的對象。需要注意的關(guān)鍵字是,新的對象,類沒變。.NET在System命名空間中提供了Cloneable接口,其中它提供唯一的方法Clone(),只需要實(shí)現(xiàn)這個(gè)接口就可以完成原型模式了。由于它直接操作內(nèi)存中的二進(jìn)制流,當(dāng)大量操作或操作復(fù)雜對象時(shí),性能優(yōu)勢將會(huì)很明顯。

三、原型模式的適用場景

多用于創(chuàng)建大對象,或初始化繁瑣的對象。如游戲中的背景,地圖。web中的畫布等等

以下場景適用:

一是類初始化需要消化非常多的資源,這個(gè)資源包括數(shù)據(jù)、硬件資源等;

二是通過 new 產(chǎn)生一個(gè)對象需要非常繁瑣的數(shù)據(jù)準(zhǔn)備或訪問權(quán)限,則可以使用原型模式;

三是一個(gè)對象需要提供給其他對象訪問,而且各個(gè)調(diào)用者可能都需要修改其值時(shí),可以考慮使用原型模式拷貝多個(gè)對象供調(diào)用者使用。

在實(shí)際項(xiàng)目中,原型模式很少單獨(dú)出現(xiàn),一般是和工廠方法模式一起出現(xiàn),通過 clone的方法創(chuàng)建一個(gè)對象,然后由工廠方法提供給調(diào)用者。

四、原型模式的實(shí)現(xiàn)

以簡歷的復(fù)印來舉例

1.淺拷貝實(shí)現(xiàn)

定義工作經(jīng)歷類

/// <summary>
/// 工作經(jīng)歷類
/// </summary>
public class WorkExperience
{
    private string _workDate;
    public string WorkDate
    {
        get { return _workDate; }
        set { _workDate = value; }
    }
     private string _company;
    public string Company
    {
        get { return _company; }
        set { _company = value; }
    }
}

定義簡歷類

/// <summary>
/// 簡歷類
/// </summary>
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();
    }
     /// <summary>
    /// 設(shè)置個(gè)人信息
    /// </summary>
    /// <param name="sex"></param>
    /// <param name="age"></param>
    public void SetPersonalInfo(string sex, string age)
    {
        this.sex = sex;
        this.age = age;
    }
     /// <summary>
    /// 設(shè)置工作經(jīng)歷
    /// </summary>
    /// <param name="workDate"></param>
    /// <param name="company"></param>
    public void SetWorkExperience(string workDate, string company)
    {
        work.WorkDate = workDate;
        work.Company = company;
    }
     /// <summary>
    /// 顯示
    /// </summary>
    public void Display()
    {
        Console.WriteLine("{0}{1}{2}", name, sex, age);
        Console.WriteLine("工作經(jīng)歷:{0}{1}", work.WorkDate, work.Company);
    }
     public object Clone()
    {
        //創(chuàng)建當(dāng)前object的淺表副本
        return (object)this.MemberwiseClone();
    }
}

客戶端調(diào)用

static void Main(string[] args)
{
    Resume a = new Resume("張三");
    a.SetPersonalInfo("男", "30");
    a.SetWorkExperience("2010-2018", "騰訊公司");
     Resume b = (Resume)a.Clone();
    b.SetWorkExperience("2010-2015", "阿里公司");
     Resume c = (Resume)a.Clone();
    c.SetPersonalInfo("女", "18");  c.SetWorkExperience("2010-2015", "百度公司");
     a.Display();
    b.Display();
    c.Display();
     Console.Read();
}

結(jié)果

張三 男 30
工作經(jīng)歷 2010-2018 騰訊公司
張三 男 30
工作經(jīng)歷 2010-2018 騰訊公司
張三 女 18
工作經(jīng)歷 2010-2018 騰訊公司

被復(fù)制對象的所有變量都含有與原來的對象相同的值,而所有的對其他對象的引用都仍然指向原來的對象,這就是淺復(fù)制。但是我們可能需要這樣一種需求,要把復(fù)制的對象所引用的對象都復(fù)制一遍。比如剛才的例子,我希望a、b、c三個(gè)引用的對象都是不同的。復(fù)制時(shí)就一變二,二變?nèi)?。此時(shí),我們就要用的方式叫“深復(fù)制”

2.深拷貝實(shí)現(xiàn)

深復(fù)制把引用對象的變量指向復(fù)制過的新對象,而不是原來被引用的對象

/// <summary>
/// 工作經(jīng)歷類
/// </summary>
public 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()
    {
        //創(chuàng)建當(dāng)前object的淺表副本
        return (object)this.MemberwiseClone();
    }
}
/// <summary>
/// 簡歷類
/// </summary>
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方法調(diào)用的私有構(gòu)造函數(shù),以便克隆“工作經(jīng)歷”數(shù)據(jù)
        this.work = (WorkExperience)work.Clone();
    }
     /// <summary>
    /// 設(shè)置個(gè)人信息
    /// </summary>
    /// <param name="sex"></param>
    /// <param name="age"></param>
    public void SetPersonalInfo(string sex, string age)
    {
        this.sex = sex;
        this.age = age;
    }
     /// <summary>
    /// 設(shè)置工作經(jīng)歷
    /// </summary>
    /// <param name="workDate"></param>
    /// <param name="company"></param>
    public void SetWorkExperience(string workDate, string company)
    {
        work.WorkDate = workDate;
        work.Company = company;
    }
     /// <summary>
    /// 顯示
    /// </summary>
    public void Display()
    {
        Console.WriteLine("{0}{1}{2}", name, sex, age);
        Console.WriteLine("工作經(jīng)歷:{0}{1}", work.WorkDate, work.Company);
    }
     public object Clone()
    {
        //調(diào)用私有的構(gòu)造方法,讓“工作經(jīng)歷”克隆完成,然后再給這個(gè)簡歷對象的相關(guān)字段賦值,
        //最終返回一個(gè)深復(fù)制的簡歷對象
        Resume obj = new Resume(this.work);
        obj.name = this.name;
        obj.sex = this.sex;
        obj.age = this.age;
        return obj;
    }
}

客戶端調(diào)用代碼一樣

結(jié)果

張三 男 30
工作經(jīng)歷 2010-2018 騰訊公司
張三 男 30
工作經(jīng)歷 2010-2015 阿里公司
張三 女 18
工作經(jīng)歷 2010-2015 百度公司

由于在一些特定場合,會(huì)經(jīng)常涉及深復(fù)制和淺復(fù)制,比如說,數(shù)據(jù)集對象DataSet,它就有Clone()方法和Copy()方法,Clone()方法用來復(fù)制DataSet的結(jié)構(gòu),但不復(fù)制DataSet的數(shù)據(jù),實(shí)現(xiàn)了原型模式的淺復(fù)制,

Copy()方法不但復(fù)制結(jié)構(gòu),還復(fù)制數(shù)據(jù),其實(shí)就是實(shí)現(xiàn)了原型模式的深復(fù)制。

五、總結(jié)

原型模式通過Object的clone()方法實(shí)現(xiàn),由于是內(nèi)存操作,無視構(gòu)造方法和訪問權(quán)限,直接獲取新的對象。但對于引用類型,需使用深拷貝,其它淺拷貝即可。

相關(guān)文章

  • 在Spring Boot中加載XML配置的完整步驟

    在Spring Boot中加載XML配置的完整步驟

    這篇文章主要給大家介紹了關(guān)于在Spring Boot中加載XML配置的完整步驟,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • Java設(shè)計(jì)模式模板方法(Template)原理解析

    Java設(shè)計(jì)模式模板方法(Template)原理解析

    這篇文章主要介紹了Java設(shè)計(jì)模式模板方法(Template)原理解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-11-11
  • SpringBoot實(shí)現(xiàn)二維碼掃碼登錄的原理及項(xiàng)目實(shí)踐

    SpringBoot實(shí)現(xiàn)二維碼掃碼登錄的原理及項(xiàng)目實(shí)踐

    本文主要介紹了SpringBoot實(shí)現(xiàn)二維碼掃碼登錄的原理及項(xiàng)目實(shí)踐,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-04-04
  • Spring Cloud Zuul添加過濾器過程解析

    Spring Cloud Zuul添加過濾器過程解析

    這篇文章主要介紹了Spring Cloud Zuul添加過濾器過程解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-12-12
  • springboot返回值轉(zhuǎn)成JSONString的處理方式

    springboot返回值轉(zhuǎn)成JSONString的處理方式

    這篇文章主要介紹了springboot返回值轉(zhuǎn)成JSONString的處理方式,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • springboot?正確的在異步線程中使用request的示例代碼

    springboot?正確的在異步線程中使用request的示例代碼

    這篇文章主要介紹了springboot中如何正確的在異步線程中使用request,本文通過示例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-07-07
  • Spring Boot使用Log4j2的實(shí)例代碼

    Spring Boot使用Log4j2的實(shí)例代碼

    這篇文章主要介紹了Spring Boot使用Log4j2的實(shí)例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-07-07
  • Springboot2.6.x的啟動(dòng)流程與自動(dòng)配置詳解

    Springboot2.6.x的啟動(dòng)流程與自動(dòng)配置詳解

    這篇文章主要給大家介紹了關(guān)于Springboot2.6.x的啟動(dòng)流程與自動(dòng)配置的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2022-01-01
  • Springmvc實(shí)現(xiàn)文件上傳

    Springmvc實(shí)現(xiàn)文件上傳

    這篇文章主要為大家詳細(xì)介紹了Springmvc實(shí)現(xiàn)文件上傳功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-10-10
  • SpringBoot異步任務(wù)使用方法詳解

    SpringBoot異步任務(wù)使用方法詳解

    這篇文章主要介紹了SpringBoot異步任務(wù)使用方法詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-03-03

最新評論