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

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

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

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

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

源碼地址設計模式

0 建造者模式簡介

0.0 建造者模式定義

建造者模式是一種常見的建立型模式,也稱生成器模式。建造者模式的通常書面化定義爲:將一個複雜對象的構建與該對象的表示分離,使得一樣的構建過程能夠建立不一樣的表示ide

建造者模式主要用於構建複雜產品,而且該產品是能夠步驟化或者模塊化的,最終能夠根據步驟或模塊組裝建立出一個複雜產品。模塊化

現實生活中咱們天天都在使用的手機有不一樣品牌不一樣型號,千差萬別,但他們都具備屏幕、電池、外殼、核心(CPU、GUPU、ROM、RAM等)共性模塊,即他們的建立過程是一致的,變化的只是每一個步驟/模塊的詳細實現細節。這種情景是使用建立者模式的最佳時機,最終產品構建過程是統一且固定的,咱們將變化的部分交給建造者,只須要配置不一樣的建造者,就可使一樣的構建過程生產出徹底不一樣的產品。ui

建造者模式的結構圖以下spa

103735-21dae004efea8394

Director:指導者,主要用來使用Buider接口,以一個統一固定的過程生產最終的產品Product設計

Builder:建造者抽象接口,定義建立一個Product對象所需各個部件的操做。在該接口中通常要求包含建立部件的方法如buidPartA,buidPartB等,同時還要包含一個獲取最終建立的複雜對象的方法getResult()。builder能夠定義爲一個抽象類或者接口

ConcreteBuilder:具體的建造者實現,繼承自Builder接口,實現接口中定義的建立部件及返回產品的方法。在這裏不一樣的建立者實現類,對同一部件或步驟進行不一樣的詳細實現,來完成不一樣產品的建立。

Product:最終產品類,表示被建造者構建出來的複雜對象,其用於多個固定的部件或步驟。

0.1 建造者模式應用場景

咱們以英雄祭壇裏造英雄這一過程爲例。在使用模式以前,咱們最直接的代碼應該像下面這樣。

惡魔獵手建立類

/// <summary>
/// 惡魔獵手建立類
/// </summary>
public class DH
{
    /// <summary>
    /// 建立英雄
    /// </summary>
    /// <returns></returns>
    public string BuilderHero()
    {
       string body = "黑夜給了我黑色眼睛,我卻用它去尋找光明。"; // 建立身體
        string weapon = "艾辛諾斯雙刃。"; // 建立武器
        string mount = "我有這雙腳有這雙腿。"; // 建立坐騎
        return body + weapon + mount;
    }
}

一樣,月之女祭司建立類

/// <summary>
/// 月之女祭司建立類
/// </summary>
public class POM
{
    /// <summary>
    /// 建立英雄
    /// </summary>
    /// <returns></returns>
    public string BuilderHero()
    {
       string body = "夜幕只爲朱顏改,羣星隕落無窮。"; // 建立身體
        string weapon = "索利達爾·羣星之怒。"; // 建立武器
        string mount = "艾斯卡達爾。"; // 建立坐騎
        return body + weapon + mount;
    }
}

客戶調用時只須要實例化不一樣的英雄建立類,來完成對應英雄的建立。

DH dh = new DH();
Console.WriteLine(dh.BuilderHero());
POM pom = new POM();
Console.WriteLine(pom.BuilderHero());
Console.ReadLine();

這樣咱們須要別的英雄時只須要再添加一個建立該英雄對應的類。

咱們這裏只是簡單的經過一句話描述建立了英雄身體、武器、坐騎三個關鍵部位,而實際中一個複雜產品的構件過程是遠遠要複雜的多,好比咱們常見的文件導出,一個文件有頭、內容、尾部說明三類內容,導出txt格式跟導出xml格式的操做,每一個部位的建立都要根據不一樣的格式進行處理。

同時咱們發現這樣一種狀況,每一個英雄建立類中建立英雄的方法其實都是同一種模式,處理步驟徹底同樣,惟一變化的部分就在於每一個步驟的具體實現細節,咱們天然會考慮

一、建立每一個英雄都要用到一樣的步驟,對與固定不變的部分,咱們要提煉出來,造成統一且公用的處理過程

二、英雄不僅這兩個,還會有不少其餘英雄須要建立,要求咱們在處理過程不變的狀況下,能實現建立不一樣英雄的須要

也就是說,咱們的固定不變的處理過程應該和變化的具體實現分離,從而達到固定處理過程的複用,同時還能知足不一樣具體實現的需求,此時的需求已經和前面介紹過的建造者模式很是貼近了。

1 建造者模式詳解

0、提煉具體產品類

將上面用字符串表示的英雄的三個特徵使用一個英雄類表示

/// <summary>
/// 英雄類
/// </summary>
public class Hero
{
    /// <summary>
    /// 身體特徵
    /// </summary>
    public string Body { get; set; }

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

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

一、建造者接口

建造者接口包含建立各部位的方法定義,及獲取最終產品方法的定義

/// <summary>
/// 建造者接口
/// </summary>
public interface IBuilder
{
    /// <summary>
    /// 建立身體特徵
    /// </summary>
    /// <returns></returns>
    void BuildBody();

    /// <summary>
    /// 建立武器
    /// </summary>
    /// <returns></returns>
    void BuildWepon();

    /// <summary>
    /// 建立坐騎
    /// </summary>
    /// <returns></returns>
    void BuildMount();

    /// <summary>
    /// 獲取最終產品
    /// </summary>
    /// <returns></returns>
    Hero GetResult();
}

二、建造者具體實現類

惡魔獵手建造者實現類

/// <summary>
/// 惡魔獵手建造者實現類
/// </summary>
public class DHBuilder : IBuilder
{
    private Hero _hero = new Hero();

    /// <summary>
    /// 建立身體特徵
    /// </summary>
    /// <returns></returns>
    public void BuildBody()
    {
        _hero.Body = "黑夜給了我黑色眼睛,我卻用它去尋找光明。";
    }

    /// <summary>
    /// 建立武器
    /// </summary>
    /// <returns></returns>
    public void BuildWeapon()
    {
        _hero.Weapon= "艾辛諾斯雙刃。";
    }

    /// <summary>
    /// 建立坐騎
    /// </summary>
    /// <returns></returns>
    public void BuildMount()
    {
        _hero.Mount= "我有這雙腳有這雙腿。";
    }

    public Hero GetResult()
    {
        return _hero;
    }
}

月之女祭司建造者類實現

/// <summary>
/// 月之女祭司建造者類
/// </summary>
public class POMBuilder : IBuilder
{
    private Hero _hero = new Hero();

    /// <summary>
    /// 建立身體特徵
    /// </summary>
    /// <returns></returns>
    public void BuildBody()
    {
        _hero.Body = "夜幕只爲朱顏改,羣星隕落無窮。";
    }

    /// <summary>
    /// 建立武器
    /// </summary>
    /// <returns></returns>
    public void BuildWeapon()
    {
        _hero.Weapon = "索利達爾·羣星之怒。";
    }

    /// <summary>
    /// 建立坐騎
    /// </summary>
    /// <returns></returns>
    public void BuildMount()
    {
        _hero.Mount = "艾斯卡達爾。";
    }

    /// <summary>
    /// 建立最終產品
    /// </summary>
    /// <returns></returns>
    public Hero GetResult()
    {
        return _hero;
    }

}

3 、指導者實現

/// <summary>
/// 指導者
/// </summary>
public class Director
{
    /// <summary>
    /// 指導方法
    /// </summary>
    public void Construct(IBuilder builder)
    {
       builder.BuildBody(); // 建立身體特徵
        builder.BuildWeapon(); // 建立武器
        builder.BuildMount(); // 建立坐騎
    }
}

四、客戶端調用

Director director = new Director();

DHBuilder buider1 = new DHBuilder();
director.Construct(buider1);
Hero dh = buider1.GetResult();

DHBuilder buider2 = new DHBuilder();
director.Construct(buider2);
Hero pom = buider1.GetResult();

2 總結

建造者模式具備一下優勢

一、鬆散耦合

建造者模式把產品的構建過程獨立出來,實現產品構建和產品表現的分離,從而使得構建算法能夠複用,同時具體產品表現也能夠靈活的擴展和切換。

二、能夠很容易改變產品內部表示

在建造者模式中,Builder只提供接口給Director使用,具體的部件建立和裝配方式有具體的建立者實現類實現,Director不關注具體實現細節,這樣一來,若是像改變產品內部的表示,只須要修改具體建造者實現類便可。

三、更好的複用性

固定建造過程能夠複用

相關文章
相關標籤/搜索