相同点:建造者模式是所有的部件在内部组装完毕之后,然后显示出来,装饰模式似乎与其有着共同之处,那就是你不能在人前一件一件地穿衣服,你肯定会在某个别人看不见的地方把衣服穿好,才出来见人的。
不同点:建造者模式要求建造的过程必须是稳定的。而装饰模式的建造过程不是稳定的,衣服你可以先穿裤子,再穿褂子,或者干脆不穿褂子,穿个短袖等等,是内部的建造过程不是稳定的。
装饰模式是对于一个东西做的是表面外部的装扮,而建造者模式是对一个东西整体框架的一个组装。
那么具体什么是装饰模式?什么又是建造者模式呢?
Ø 装饰模式
装饰模式(Decorator):动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活。
程序代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication7
{
class Person
{
public Person()
{ }
private string name;
public Person(string name)
{
this.name = name;
}
public virtual void Show()
{
Console.WriteLine("装扮{0}",name );
}
}
class Finery : Person
{
protected Person component;
//打扮
public void Decorate(Person component)
{
this.component = component;
}
public override void Show()
{
if (component != null)
{
component.Show();
}
}
}
class TShirts : Finery
{
public override void Show()
{
Console.Write("大体恤");
base.Show ();
}
}
class BigTrouser : Finery
{
public override void Show()
{
Console.Write("垮裤");
base.Show();
}
}
class Sneakers : Finery
{
public override void Show()
{
Console.Write("破球鞋");
base.Show();
}
}
class LeatherShoes : Finery
{
public override void Show()
{
Console.Write("皮鞋");
base.Show();
}
}
class Suit : Finery
{
public override void Show()
{
Console.Write("西装");
base.Show();
}
}
class Tie : Finery
{
public override void Show()
{
Console.Write("领带");
base.Show();
}
}
}
客户端代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication7
{
class Program
{
static void Main(string[] args)
{
Person xc = new Person("小菜");
Console.WriteLine ("\n第一种装扮:");
Sneakers pqx=new Sneakers ();
BigTrouser kk=new BigTrouser ();
TShirts dtx=new TShirts ();
pqx .Decorate (xc);
kk.Decorate (pqx);
dtx.Decorate (kk);
dtx.Show ();
Console.WriteLine ("\n第二种装扮:");
LeatherShoes px=new LeatherShoes ();
Tie ld=new Tie ();
Suit xz=new Suit ();
px.Decorate (xc);
ld.Decorate (px);
xz.Decorate (ld);
xz.Show ();
Console.Read();
}
}
}
Ø 建造者模式
建造者模式(Builder):将一个复杂对象的构建和它的表示相分离,使得同样的构建过程可以创建不同的表示。
程序代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
namespace ConsoleApplication8
{
//class Graphics
//{
// IList <string >parts=new List <string >;
// public void Add(string part)
// {
// parts.Add (part );
// }
// public void Show()
// {
// Console.WriteLine ("\n图 创建头、身体、左手、右手、左腿、右腿");
// foreach (string part in parts)
// {
// Console.WriteLine (part);
// }
// }
//}
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 BuildBody();
public abstract void BuildArmLeft();
public abstract void BuildArmRight();
public abstract void BuildLegLeft();
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 BuildBody()
{
g.DrawRectangle(p,60,50,10,50);
}
public override void BuildArmLeft()
{
g.DrawLine(p,60,50,40,100);
}
public override void BuildArmRight()
{
g.DrawLine(p,70,50,90,100);
}
public override void BuildLegLeft()
{
g.DrawLine(p,60,100,45,150);
}
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.BuildBody();
pb.BuildArmLeft();
pb.BuildArmRight();
pb.BuildLegLeft();
pb.BuildLegRight();
}
}
}
客户端代码
Pen p = new Pen(Color.Yellow);
PersonThinBuilder ptb = new PersonThinBuilder(pictureBox1.CreateGraphics(),p);
PersonDirector pbThin = new PersonDirector(ptb);
pbThin .CreatePerson();
Ø 两者的比较
u 装饰模式
由上例我们可以看出,装饰模式把每个要装饰的功能放在单独的类中,并让这个类包装它所要修饰的对象,因此,当需要执行特殊行为的时候,客户代码就可以在运行时根据需要有选择地、按顺序地使用装饰功能包装对象了。
优点:把类中的装饰功能从类中搬移去除,这样简化了原来的类。
有效地把类的核心职责与装饰功能区分开了。并且可以去除相关类中重复的装饰逻辑。
缺点:1. 这种比继承更加灵活机动的特性,也同时意味着更加多的复杂性。
2. 装饰模式会导致设计中出现许多小类,如果过度使用,会使程序变得很复杂。
3. 装饰模式是针对抽象组件(Component)类型编程。但是,如果你要针对具体组件编程时,就应 该重新思考你的应用架构,以及装饰者是否合适。当然也可以改变Component接口,增加新的公开的行为, 实现“半透明”的装饰者模式。在实际项目中要做出最佳选择。
4、此外装饰模式的顺序很重要,如加密数据和过滤词汇如果先加密再过滤。肯定是会出问题的。
u 建造者模式
由上例可以看出,建造者主要用于创建一些复杂的对象,这些对象内部构建间的建造顺序通常是稳定的,但是对象内部的构件通常是面临着复杂的变化。
优点就是:使得建造代码与表示代码分离。由于建造者隐藏了该产品是如何组装的,所以若需要改变一个产品的内部表示,只需要再定义一个具体的建造者就可以了。
这不免要想起工厂模式以及抽象工厂模式等等,它们的共同点就是使用者不必知道内部组成的细节,但是又有所不一样,那就是建造者模式最主要的功能是基本方法的调用顺序的安排,这些基本方法已经实现,而工厂方法则重点是创建,组装顺序则不关心。
不同于抽象工厂的地方是:在抽象工厂模式中,客户端实例化工厂类,然后调用工厂方法获取所需产品对象,而在建造者模式中,客户端可以不直接调用建造者的相关方法,而是通过指挥者类来指导如何生成对象,包括对象的组装过程和建造步骤,它侧重于一步步构造一个复杂对象,返回一个完整的对象。
Ø 小结
u 装饰模式与建造者模式比较表
此外无论是建造模式还是装饰模式,以及其他的模式,我们几乎都能看到一个抽象出来的东西,就是抽象类或者接口,那么这两者又有什么区别呢,我们下一篇来讲述。