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


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

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

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

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

  • 相关阅读:
    asp.net webform 动态调试技巧
    SQL RAND() 返回一个介于 0 到 1(不包括 0 和 1)之间的伪随机 float 值。
    SQL GUID之 NEWID()、NEWSEQUENTIALID()、UUID()、UUID_SHORT() 全局通用唯一标识符
    Linux环境下GraalVM nativeimage将jar包编译为二进制
    idea设置@vue跳转
    elupload 点击阻止弹窗
    使用Kotlin开发多平台应用
    你了解业务吗
    SQL 的理论基础是关系代数,而关系代数的主要操作只有 5 种,分别是并、差、积、选择、投影。所有的 SQL 语句最后都能用这 5 种操作组合完成。而一个嵌套子查询可以等价转换成一个连接(join)操作
    NO ONE CAN BEAT US
  • 原文地址:https://www.cnblogs.com/liuhuimh/p/10664173.html
Copyright © 2020-2023  润新知