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

本文介绍了如何使用建造者模式简化绘制不同人物形象的过程,并逐步优化代码结构。从初始的非面向对象设计开始,逐步引入抽象类、子类继承及Director模式,最终通过反射机制进一步增强灵活性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值