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

来源:互联网 发布:看病预约软件哪个好 编辑:程序博客网 时间:2024/06/05 05:17

现在有个需求:点击一下按钮画两个人,胖人和瘦人,简单起见,这里只画头和右腿,通过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。

原创粉丝点击