设计模式----建造者模式

        今天,我们来学习下建造者模式,这个模式,听名字就知道和建筑有关系嘛,建筑在我们日常生活中相当常见,建筑它有什么特点呢?首先,它们都有墙,有门,有窗等等,总而言之,言而总之,它们都是由固定的模式组合而成的,今天,就让我们按照建造房子的模式来学习这个建造者模式。。

        今天的场景,我们不是建房子,我们在电脑上建造一个小人,和房子一个道理,每个人都有头,手,脚,身体等等一系列构成,好的,开始我们的学习,首先,设计模式第一步,抽象,上代码

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哈哈~),好了,今天的建造者模式就学完了,最后,总结一下吧,建造者模式只适用在一些亘古不变的场景下使用,例如我们今天说的房屋和人,这些部件它们都是不会如何变化的。。

        设计模式虽然巧妙,但是也不可滥用

posted @ 2019-04-07 10:00  守望阳光01  阅读(169)  评论(0编辑  收藏  举报