增强可读性,易用性——设计模式之建造者模式(灵活使用继承和抽象类以及抽象函数和反射)

现在有个需求:点击一下按钮画两个人,胖人和瘦人,简单起见,这里只画头和右腿,通过Pen类和Graphics类。

基本的代码如下:

private void button1_Click(object sender, EventArgs e)
        {
            Pen p = new Pen(Color.Yellow);


            Graphics gThin = pictureBox1.CreateGraphics();
            gThin.DrawEllipse(p, 50, 20, 30, 30);
            gThin.DrawRectangle(p, 60, 50, 10, 50);


            Graphics gFat = pictureBox2.CreateGraphics();
            gFat.DrawEllipse(p, 50, 20, 30, 30);
            gFat.DrawLine(p, 70, 100, 85, 150);
        }
很明显,缺乏面向对象的设计,而且不能重用,可读性很差。

第一级

现我们定义两个类

namespace 建造者模式一级
{

    class PersonThinBuilder
    {
        private Graphics g;
        private Pen p;

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

        public void Build()
        {
            g.DrawEllipse(p, 50, 20, 30, 30);
            g.DrawLine(p, 70, 100, 85, 150);
        }
    }

    class PersonFatBuilder
    {
        private Graphics g;
        private Pen p;

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

        public void Build()
        {
            g.DrawEllipse(p, 50, 20, 30, 30);
            g.DrawLine(p, 70, 100, 85, 150);
        }
    }
}
将前面画两个图的功能用来两个类来实现,客户端调用的代码就变成了

private void button1_Click(object sender, EventArgs e)
        {

            Pen p = new Pen(Color.Yellow);

            Graphics gThin = pictureBox1.CreateGraphics();

            PersonThinBuilder ptb = new PersonThinBuilder(gThin, p);
            ptb.Build();

            Graphics gFat = pictureBox2.CreateGraphics();

            PersonFatBuilder pfb = new PersonFatBuilder(gFat, p);
            pfb.Build();
        }
初步具有面向对象的结构了,可是这样觉得还是不够好,因为这两个类很明显有共同的地方,我们的目标就是抽取共同的地方,而且可读性很差。

第二级

定义类如下

namespace 建造者模式二级
{
    abstract class PersonBuilder
    {
        protected Graphics g;
        protected Pen p;

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

        public abstract void BuildHead();
        public abstract void BuildLegRight();
    }

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

        public override void BuildHead()
        {
            g.DrawEllipse(p, 50, 20, 30, 30);
        }
        public override void BuildLegRight()
        {
            g.DrawLine(p, 70, 100, 85, 150);
        }
    }

    class PersonFatBuilder : PersonBuilder
    {
        public PersonFatBuilder(Graphics g, Pen p)
            : base(g, p)
        { }

        public override void BuildHead()
        {
            g.DrawEllipse(p, 50, 20, 30, 30);
        }
        public override void BuildLegRight()
        {
            g.DrawLine(p, 70, 100, 85, 150);
        }
    }

    class PersonDirector
    {
        private PersonBuilder pb;
        public PersonDirector(PersonBuilder pb)
        {
            this.pb = pb;
        }

        public void CreatePerson()
        {
            pb.BuildHead();
            pb.BuildLegRight();
        }
    }
}

很明显,定义了一个抽象父类PersonBuilder,里面定义了两个抽象函数,为BuildHead()和BuildLegRight.()意思很明白吧,画头和画右腿,首先这样处理的一个好处是可读性强了吧,然后就是后面定义了胖人和瘦人这两个类,继承PersonBuilder类,在这两个子类中再具体实现了怎么画头和右腿,还有个PersonDirector的类,这个类就提供了个灵活的接口,传递个PersonBuilder参数过来后,不管是画胖人还是瘦人,只调用它的CreatPerson()方法就可以了.

客户端代码如下:

private void button1_Click(object sender, EventArgs e)
{
            Pen p = new Pen(Color.Yellow);
            PersonThinBuilder ptb = new PersonThinBuilder(pictureBox1.CreateGraphics(), p);
            PersonDirector pdThin = new PersonDirector(ptb);
            pdThin.CreatePerson();

            PersonFatBuilder pfb = new PersonFatBuilder(pictureBox2.CreateGraphics(), p);
            PersonDirector pdFat = new PersonDirector(pfb);
            pdFat.CreatePerson();

        }

现在调用起来是不是又易于理解又方便呢,若是要画胳膊啊,肚子啊的,就在PersonBuilder中加抽象函数,然后在胖人和瘦人类中再具体实现,客户端的代码完全不用改哦,就可以实现了。看看,好处很明显吧。

下面介绍下利用反射机制Assembly类实现

第三级

类的代码如下:

namespace 建造者模式第三级
{
    abstract class PersonBuilder
    {
        protected Graphics g;
        protected Pen p;

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

        public abstract void BuildHead();
        public abstract void BuildLegRight();
    }

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

        public override void BuildHead()
        {
            g.DrawEllipse(p, 50, 20, 30, 30);
        }
        public override void BuildLegRight()
        {
            g.DrawLine(p, 70, 100, 85, 150);
        }
    }

    class PersonFatBuilder : PersonBuilder
    {
        public PersonFatBuilder(Graphics g, Pen p)
            : base(g, p)
        { }

        public override void BuildHead()
        {
            g.DrawEllipse(p, 50, 20, 30, 30);
        }
        public override void BuildLegRight()
        {
            g.DrawLine(p, 70, 100, 85, 150);
        }
    }

    class PersonDirector
    {
        private PersonBuilder pb;
        public PersonDirector(string type, Graphics g, Pen p)
        {
            string assemblyName="建造者模式第三级";
            object[] args = new object[2];
            args[0] = g;
            args[1] = p;

            this.pb = (PersonBuilder)Assembly.Load(assemblyName).CreateInstance(assemblyName+".Person" + type + "Builder", false, BindingFlags.Default, null, args, null, null);
        }

        public void CreatePerson()
        {
            pb.BuildHead();
            pb.BuildLegRight();
        }
    }
}

客户端代码如下:

private void button1_Click(object sender, EventArgs e)
        {
            Pen p = new Pen(Color.Yellow);
            PersonDirector pdThin = new PersonDirector("Thin",pictureBox1.CreateGraphics(),p);
            pdThin.CreatePerson();

            PersonDirector pdFat = new PersonDirector("Fat", pictureBox2.CreateGraphics(), p);
            pdFat.CreatePerson();
        }
在调用时传递"Thin"和“Fat"参数,PersonDirect类中反射出对应的瘦人和胖人的类。
(PersonBuilder)Assembly.Load(assemblyName).CreateInstance(assemblyName+".Person" + type + "Builder", false, BindingFlags.Default, null, args, null, null);
这段代码可以好好的研究下,里面参数的意义,可以自己查询msn。

你可能感兴趣的:(设计模式,object,assembly,null,Class,button)