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