設計模式----建造者模式

守望陽光01發表於2019-04-07

        今天,我們來學習下建造者模式,這個模式,聽名字就知道和建築有關係嘛,建築在我們日常生活中相當常見,建築它有什麼特點呢?首先,它們都有牆,有門,有窗等等,總而言之,言而總之,它們都是由固定的模式組合而成的,今天,就讓我們按照建造房子的模式來學習這個建造者模式。。

        今天的場景,我們不是建房子,我們在電腦上建造一個小人,和房子一個道理,每個人都有頭,手,腳,身體等等一系列構成,好的,開始我們的學習,首先,設計模式第一步,抽象,上程式碼

abstract class PersonBuider
    {
        protected Graphics g;
        protected Pen p;

        public PersonBuider(Graphics g, Pen p)
        {
            this.g = g;
            this.p = p;
        }

        public abstract void BuidHead();
        public abstract void BuidBody();
        public abstract void BuidArmLeft();
        public abstract void BuidArmRight();
        public abstract void BuidLegLeft();
        public abstract void BuidLegRight();
    }

        上面這個PersonBuider類,看名字就知道大概了,我們分析下它裡面的內容,首先,建構函式注入,幾乎設計模式都用到的東西,注入兩個環境提供的類,畫布和畫筆,然後是定義了六個抽象方法,對應的我們的身體各部,其實也很簡單,一目瞭然,接下來,根據以往的套路來看,既然定義了抽象,那麼肯定就要實現了啊。這是必須的,不然抽象就無用了呢

class PersonThinBuilder : PersonBuider
    {
        public PersonThinBuilder(Graphics g, Pen p) : base(g, p)
        {

        }
        public override void BuidHead()
        {
            g.DrawEllipse(p, 50, 20, 30, 30);
        }
        public override void BuidBody()
        {
            g.DrawRectangle(p, 60, 50, 10, 50);
        }
        public override void BuidArmLeft()
        {
            g.DrawLine(p, 60, 50, 40, 100);
        }
        public override void BuidArmRight()
        {
            g.DrawLine(p, 70, 50, 90, 100);
        }
        public override void BuidLegLeft()
        {
            g.DrawLine(p, 60, 100, 45, 150);
        }
        public override void BuidLegRight()
        {
            g.DrawLine(p, 70, 100, 85, 150);
        }
    }

        這裡,我們建立一個PersonThinBuilder類實現了PersonBuider類,誒,這裡,我們又看到了上次裝飾器模式裡的建構函式注入,它用了base關鍵字,這個關鍵字的作用我們在裝飾器一文程式碼中有註釋,是呼叫父類建構函式的意思,為什麼要這麼寫呢,我們先看完建造者模式所有骨架之後我們再來分析一波,好的,我們的PersonThinBuilder實現類,重寫了我們抽象類的六個抽象方法,這裡就是建立我們具體的人的各個部位,好了,現在我們都具備了建立各個零件的能力,接下來,就是去實際生成了

class PersonDirector
    {
        private PersonBuider pb;
        public PersonDirector(PersonBuider pb)
        {
            this.pb = pb;
        }
        public void CreatePerson()
        {
            pb.BuidHead();
            pb.BuidBody();
            pb.BuidArmLeft();
            pb.BuidArmRight();
            pb.BuidLegLeft();
            pb.BuidLegRight();
        }
    }

        看到我們這個PersonDirector類的建構函式應該不陌生了吧,它再一次的用了建構函式注入,這次,它注入的是我們的抽象類PersonBuider,然後它自身有一個方法,這個方法的內部就是分別呼叫了抽象類的六個抽象方法,到這裡,我們建造者模式的所有骨架基本完成了,現在,讓我們看看上層呼叫實現,是如何把一個小人給組合起來的吧

public void DrawPerson()
        {
            Pen p = new Pen(Color.Red);
            PersonThinBuilder ptb = new PersonThinBuilder(pictureBox1.CreateGraphics(), p);
            PersonDirector pdThin = new PersonDirector(ptb);
            pdThin.CreatePerson();
        }                                                                                                                       

        private void button1_Click(object sender, EventArgs e)
        {
            DrawPerson();
        }

        這裡我們用的是winForm去實現,這樣我們能更清晰的看到效果,上面的程式碼就是上層的實現了,首先,它new了一個PersonThinBuilder類,然後再new了一個PersonDirector類,這裡,我們解釋一下剛才我們的疑問,首先是new一個PersonThinBuilder類,我們注意到,它例項化的時候傳了一個畫布例項和一個畫筆例項,這是為什麼呢,因為它繼承了PersonBuider類,當我們去例項化PersonThinBuilder的類的時候,如果這個時候我們去除錯程式碼就會知道,它會率先去例項PersonBuider類,而PersonBuider類的例項需要一個畫布和一個畫筆,所以,我們在new一個PersonThinBuilder類的時候才傳入這兩個物件的,所以,這才能解釋為什麼PersonThinBuilder ptb = new PersonThinBuilder(pictureBox1.CreateGraphics(), p);這個語句會成立的根本原因。接下來,我們來解釋下為什麼要這麼傳參,就是所謂的建構函式注入,建構函式注入的用意在於解耦,在類關係中,組合關係是類和類關係最鬆散的一種,使用建構函式注入,可以讓我們不用在呼叫類的裡面去例項我們需要呼叫的型別,而是把它們延遲到我們的最上層是例項,意思就是在我們寫程式碼的時候不用去new它,而是在我們上端實現的時候去new它,這也解釋了PersonThinBuilder類建構函式為什麼用base這個關鍵字了,因為在PersonThinBuilder類的內部我們根本沒有用到,所以無需建構函式注入,PersonThinBuilder類的構造只是起到一個橋樑作用。好了,疑問解答完畢,接下來,讓我們看看我們實現的小人吧

        這個就是我們大費周章得到的小人了,一看就知道骨骼清奇(O(∩_∩)O哈哈~),好了,今天的建造者模式就學完了,最後,總結一下吧,建造者模式只適用在一些亙古不變的場景下使用,例如我們今天說的房屋和人,這些部件它們都是不會如何變化的。。

        設計模式雖然巧妙,但是也不可濫用

相關文章