設計模式(5)原型模式(Prototype)

設計模式(0)簡單工廠模式html

設計模式(1)單例模式(Singleton)git

設計模式(2)工廠方法模式(Factory Method)github

設計模式(3)抽象工廠模式(Abstract Factory)設計模式

設計模式(4)建造者模式/生成器模式(Builder)ui

源碼地址spa

0 原型模式簡介

0.0 原型模式定義

原型模式是一種經常使用的建立型模式,原型模式的通常定義爲用原型實例指定建立對象的種類,並經過拷貝這些原型建立新的對象設計

原型模式要求對象必須具備一個能夠「克隆」自身的方法,這樣就能夠經過這個克隆自身的方法建立一個新的同一類型的實例。咱們一般將這個克隆自身的方法定義在抽象的接口上,直接經過接口調用其內部包含的克隆方法,建立一個具體的對象。這樣就能夠實現經過原型模式建立具體對象,無需關注這個對象自己的類型,也不用關心其內部的具體實現,而無須再去經過new去建立具體的類型的實例。code

原型模式的結構圖以下htm

timg

Prototype:聲明一個克隆自身的接口,用來約束想要克隆自身的類,全部想要實現克隆自身這一功能的類須要繼承此接口,而且實現該接口裏定義的克隆自身的方法對象

ConcretePrototype:實現了Prototype接口的具體實現類,這些類中負責Clone這一方法的具體實現

Client:客戶端,經過原型實例克隆自身的Clone方法建立新的對象實例

0.1 原型模式應用場景

在war3中,有一個道具叫作「幻象權杖」其做用是使用後能製造目標單位的一個幻象。咱們不考究幻象的其餘具體細節,從外形上是與本體徹底一摸同樣的。

咱們先建立一個英雄的接口

/// <summary>
/// 英雄接口定義
/// </summary>
public interface IHero
{
    /// <summary>
    /// 身體特徵
    /// </summary>
    string Body { get; set; }

    /// <summary>
    /// 武器
    /// </summary>
    string Weapon { get; set; }

    /// <summary>
    /// 坐騎
    /// </summary>
    string Mount { get; set; }
}

DH類具體實現

/// <summary>
/// 惡魔獵手
/// </summary>
public class DH : IHero
{

    /// <summary>
    /// 身體特徵
    /// </summary>
    public string Body
    {
        get { return "黑夜給了我黑色眼睛,我卻用它去尋找光明。"; }
        set { }
    }

    /// <summary>
    /// 武器
    /// </summary>
    public string Weapon
    {
        get { return "艾辛諾斯雙刃。"; }
        set { }
    }

    /// <summary>
    /// 坐騎
    /// </summary>
    public string Mount
    {
        get { return "我有這雙腳有這雙腿。"; }
        set { }
    }
}

POM類具體實現

/// <summary>
/// 月亮女祭司
/// </summary>
public class POM : IHero
{
    /// <summary>
    /// 身體特徵
    /// </summary>
    public string Body
    {
        get { return "夜幕只爲朱顏改,羣星隕落無窮。"; }
        set { }
    }

    /// <summary>
    /// 武器
    /// </summary>
    public string Weapon
    {
        get { return "索利達爾·羣星之怒。"; }
        set { }
    }

    /// <summary>
    /// 坐騎
    /// </summary>
    public string Mount
    {
        get { return "艾斯卡達爾。"; }
        set { }
    }
}

幻象權杖類實現

/// <summary>
/// 幻象權杖
/// </summary>
public class WandOfIllusion
{
    public static IHero Use(IHero hero)
    {
        IHero result = null;
        if (hero is DH)
        {
            result = new DH();
        }
        else if (hero is POM)
        {
            result = new POM();
        }
        return result;
    }
}

客戶端使用

class Program
{
    static void Main(string[] args)
    {
        DH dh = new DH();
        var dh1 = WandOfIllusion.Use(dh); // 對dh使用幻象權杖
        Console.ReadLine();
    }
}

這樣能夠實現英雄使用幻象權杖複製自身這一基本需求,可是明顯存在一下問題

一、經過幻象權杖複製英雄對象自己 這一通用的功能代碼中,不該該強依賴具體的英雄類,應該是與具體的實現無關的。

二、難以擴展,要實現其餘英雄使用幻象權杖這一操做,就必須修改幻象權杖類,裏面須要增長更多的類型判斷。並且咱們這裏只作了簡要的對象建立處理,而實際中各個對象的建立過程是千差萬別的,這樣咱們的幻象權杖類就會變得愈來愈難以維護。

基於問題的出現以及上述對原型模式的介紹,咱們可使用原型模式解決這一問題。

1 原型模式詳解

0、英雄接口增長Clone方法

按照原型模式的要求,咱們須要在英雄接口中增長一個Clone方法,全部英雄的具體實現類實現此方法,完成複製英雄的具體細節。

/// <summary>
/// 英雄接口定義
/// </summary>
public interface IHero
{
    /// <summary>
    /// 身體特徵
    /// </summary>
    string Body { get; set; }

    /// <summary>
    /// 武器
    /// </summary>
    string Weapon { get; set; }

    /// <summary>
    /// 坐騎
    /// </summary>
    string Mount { get; set; }

    /// <summary>
    /// Clone自己接口定義
    /// </summary>
    /// <returns></returns>
    IHero Clone();
}

一、具體英雄實現類實現Clone方法

/// <summary>
/// 惡魔獵手
/// </summary>
public class DH : IHero
{

    /// <summary>
    /// 身體特徵
    /// </summary>
    public string Body
    {
        get { return "黑夜給了我黑色眼睛,我卻用它去尋找光明。"; }
        set { }
    }

    /// <summary>
    /// 武器
    /// </summary>
    public string Weapon
    {
        get { return "艾辛諾斯雙刃。"; }
        set { }
    }

    /// <summary>
    /// 坐騎
    /// </summary>
    public string Mount
    {
        get { return "我有這雙腳有這雙腿。"; }
        set { }
    }

    /// <summary>
    /// Clone
    /// </summary>
    /// <returns></returns>
    public IHero Clone()
    {
        IHero hero = new DH();
        //TODO:進行其餘Clone相關操做
        return hero;
    }
}
/// <summary>
/// 月亮女祭司
/// </summary>
public class POM : IHero
{
    /// <summary>
    /// 身體特徵
    /// </summary>
    public string Body
    {
        get { return "夜幕只爲朱顏改,羣星隕落無窮。"; }
        set { }
    }

    /// <summary>
    /// 武器
    /// </summary>
    public string Weapon
    {
        get { return "索利達爾·羣星之怒。"; }
        set { }
    }

    /// <summary>
    /// 坐騎
    /// </summary>
    public string Mount
    {
        get { return "艾斯卡達爾。"; }
        set { }
    }

    /// <summary>
    /// Clone
    /// </summary>
    /// <returns></returns>
    public IHero Clone()
    {
        IHero hero = new POM();
        //TODO:進行其餘Clone相關操做
        return hero;
    }
}

二、修改幻象權杖類

/// <summary>
/// 幻象權杖
/// </summary>
public class WandOfIllusion
{
    public static IHero Use(IHero hero)
    {
        IHero result = null;
        //if (hero is DH)
        //{
        //    result = new DH();
        //}
        //else if (hero is POM)
        //{
        //    result = new POM();
        //}
        result = hero.Clone();
        return result;
    }
}

至此咱們的幻象權杖通用類,已經與具體的英雄實現類無關了。

三、淺克隆和深克隆

淺克隆:只克隆值類型的屬性數據

深克隆:除了要複製淺克隆須要複製的值類型屬性數據外,也要複製引用類型的屬性數據。

2 總結

優勢

對客戶端調用隱藏具體實現類細節,減小外部調用對具體實現類的依賴

缺點

每一個實現類都必須實現Clone方法,尤爲在包含引用類型的深克隆時,須要逐級讓全部的引用類型實現Clone

相關文章
相關標籤/搜索