Dot Net设计模式—生成器模式
1.概要
1.1意图
将复杂对象的构建与表示分离,使得同样的构建过程可以创建不同的表示。需要注意如下几点。
(1)构建与表示分离:表明生成器模式的结构,构建过程被封装在导航器中,生成器则负责实现具体的表示。
(2)同样的构建过程:生成器模式关注的是构建过程,即构建过程是相同的。
(3)不同的表示:生成器模式并不在意产生对象的结果,其构造的产品不一定有相同的类型。
1.2使用场合
创建复杂对象的算法应该独立于该对象的组成部分及其装配方式,以及构造过程必须允许被构造的对象有不同表示情况下使用生成器模式。
1.3结构
生成器模式的结构如图所示。
(1)Builder:为创建Product对象的各个部件指定抽象接口。
(2)ConcreteBuilder:实现Builder的接口以构造和装配该产品的各个部件,定义并
明确它所创建的表示,并提供一个检索产品的接口。
(3)Director:构造一个使用Builder接口的对象。
(4)Product:表示被构造的复杂对象。ConcreteBuilder创建该产品的内部表示并定
义它的装配过程,包含定义组成部件的类,以及将这些部件装配成最终产品的接口。
1.4实现示例
先用一个一个简单的例子来说明生成器模式的代码实现。编写一个画脸谱程序,将画脸谱的过程分解为画脸、画眼睛、画鼻子、画耳朵和画嘴巴。首先创建一个抽象的生成器,命名为FaceBuilder:
然后创建一个具体的生成器,使用GUI+绘制脸谱:
接着创建绘制导航:
最后可以在一个窗体中调用:
GUIFaceBuilder b = new GUIFaceBuilder ( this.CreateGraphics ());
FaceDirector c = new FaceDirector (b);
c.CreateFace ();
结构如图:
2.效果
采用生成器模式可以轻松地改变产品的内部表示,上例中的脸谱画得不太好。但是如果我们创建一个新的生成器,艺术地绘制脸谱的各个部分,即可改善脸谱的质量。而这项工作完全可以和程序主体分离,由一位爱好美术的程序员独立完成。
生成器模式将构造代码和表示代码分开,一个脸谱可以用位图、字符串或对象模型来表示,构造代码完全一致。
构造过程可以更精细地控制,生成器模式强调的是产品的构造过程,产品各部分具有依赖关系非常重要。
需要注意的是,不同生成器产生的对象可能不属于同一类型,因此使用生成器的客户必须知道产品的具体类型。例如在创建脸谱的示例中,产生的GUI脸谱和脸谱对象是完全不同的类型。这意味着生成器经常不能互换,不同的生成器针对的客户程序也不相同。
3.生成器模式与抽象工厂的区别
生成器模式关注于将构造对象的过程和构造的各个部分分开,而抽象工厂关注于构建一个产品系列。实际上,最大的区别是生成器模式创建的产品不一定有共同的父类,只要有类似的构造过程即可。在上例中,FaceBuilder仅仅抽象了构建过程,并没有规定一定产生的产品类型,具体的产品由具体的Builder类决定。从上例产生的一个简单的Graphics对象中我们可以获得一个脸谱的位图,但也可用相同的导航器和结构获得一个Face对象。
实际上我们常见到的文件资源管理器的实现完全可以使用生成器模式。由于时间关系,这里不再讲述。有可能在以后的模式中涉及到这些。
1.1意图
将复杂对象的构建与表示分离,使得同样的构建过程可以创建不同的表示。需要注意如下几点。
(1)构建与表示分离:表明生成器模式的结构,构建过程被封装在导航器中,生成器则负责实现具体的表示。
(2)同样的构建过程:生成器模式关注的是构建过程,即构建过程是相同的。
(3)不同的表示:生成器模式并不在意产生对象的结果,其构造的产品不一定有相同的类型。
1.2使用场合
创建复杂对象的算法应该独立于该对象的组成部分及其装配方式,以及构造过程必须允许被构造的对象有不同表示情况下使用生成器模式。
1.3结构
生成器模式的结构如图所示。
(1)Builder:为创建Product对象的各个部件指定抽象接口。
(2)ConcreteBuilder:实现Builder的接口以构造和装配该产品的各个部件,定义并
明确它所创建的表示,并提供一个检索产品的接口。
(3)Director:构造一个使用Builder接口的对象。
(4)Product:表示被构造的复杂对象。ConcreteBuilder创建该产品的内部表示并定
义它的装配过程,包含定义组成部件的类,以及将这些部件装配成最终产品的接口。
1.4实现示例
先用一个一个简单的例子来说明生成器模式的代码实现。编写一个画脸谱程序,将画脸谱的过程分解为画脸、画眼睛、画鼻子、画耳朵和画嘴巴。首先创建一个抽象的生成器,命名为FaceBuilder:
using System;
namespace FaceBuilder
{
public abstract class FaceBuilder()
{}
public abstract void BuildFace();
public abstract void BuildEyes();
public abstract void BuildNose();
public abstract void BuildEars();
public abstract void BuildMouth();
}
namespace FaceBuilder
{
public abstract class FaceBuilder()
{}
public abstract void BuildFace();
public abstract void BuildEyes();
public abstract void BuildNose();
public abstract void BuildEars();
public abstract void BuildMouth();
}
然后创建一个具体的生成器,使用GUI+绘制脸谱:
using System;
using System.Drawing;
namespace FaceBuilder
{
public class GUIFaceBuilder:FaceBuilder
{
private Graphics grap;
private Pen p;
public GUIFaceBuilder(Graphics g)
{
grap = p;
p = new Pen (Color.Blue);
}
public override void BuildFace ()
{
grap.DrawEllipse (p,100,100,200,300);
}
public override void BuildEyes ()
{
grap.DrawEllipse (p,125,220,50,30);
grap.DrawEllipse (p,225,220,50,30);
}
public override void BuildEars ()
{
grap.DrawEllipse (p,80,250,20,40);
grap.DrawEllipse (p,300,250,20,40);
}
public override void BuildNose ()
{
grap.DrawEllipse (p,190,250,20,50);
}
public override void BuildNose ()
{
grap.DrawEllipse (p,190,350,20,1);
}
}
}
using System.Drawing;
namespace FaceBuilder
{
public class GUIFaceBuilder:FaceBuilder
{
private Graphics grap;
private Pen p;
public GUIFaceBuilder(Graphics g)
{
grap = p;
p = new Pen (Color.Blue);
}
public override void BuildFace ()
{
grap.DrawEllipse (p,100,100,200,300);
}
public override void BuildEyes ()
{
grap.DrawEllipse (p,125,220,50,30);
grap.DrawEllipse (p,225,220,50,30);
}
public override void BuildEars ()
{
grap.DrawEllipse (p,80,250,20,40);
grap.DrawEllipse (p,300,250,20,40);
}
public override void BuildNose ()
{
grap.DrawEllipse (p,190,250,20,50);
}
public override void BuildNose ()
{
grap.DrawEllipse (p,190,350,20,1);
}
}
}
接着创建绘制导航:
using System;
namespace FaceBuilder
{
public class FaceDirector
{
private class FaceBuilder b;
public FaceDirector (FaceBuilder b)
{
this.b = b;
}
public void CreateFace ()
{
b. BuildFace ();
b. BuildEyes ();
b. BuildEars ();
b. BuildNose ();
b. BuildNose ();
}
}
}
namespace FaceBuilder
{
public class FaceDirector
{
private class FaceBuilder b;
public FaceDirector (FaceBuilder b)
{
this.b = b;
}
public void CreateFace ()
{
b. BuildFace ();
b. BuildEyes ();
b. BuildEars ();
b. BuildNose ();
b. BuildNose ();
}
}
}
最后可以在一个窗体中调用:
GUIFaceBuilder b = new GUIFaceBuilder ( this.CreateGraphics ());
FaceDirector c = new FaceDirector (b);
c.CreateFace ();
结构如图:
2.效果
采用生成器模式可以轻松地改变产品的内部表示,上例中的脸谱画得不太好。但是如果我们创建一个新的生成器,艺术地绘制脸谱的各个部分,即可改善脸谱的质量。而这项工作完全可以和程序主体分离,由一位爱好美术的程序员独立完成。
生成器模式将构造代码和表示代码分开,一个脸谱可以用位图、字符串或对象模型来表示,构造代码完全一致。
构造过程可以更精细地控制,生成器模式强调的是产品的构造过程,产品各部分具有依赖关系非常重要。
需要注意的是,不同生成器产生的对象可能不属于同一类型,因此使用生成器的客户必须知道产品的具体类型。例如在创建脸谱的示例中,产生的GUI脸谱和脸谱对象是完全不同的类型。这意味着生成器经常不能互换,不同的生成器针对的客户程序也不相同。
3.生成器模式与抽象工厂的区别
生成器模式关注于将构造对象的过程和构造的各个部分分开,而抽象工厂关注于构建一个产品系列。实际上,最大的区别是生成器模式创建的产品不一定有共同的父类,只要有类似的构造过程即可。在上例中,FaceBuilder仅仅抽象了构建过程,并没有规定一定产生的产品类型,具体的产品由具体的Builder类决定。从上例产生的一个简单的Graphics对象中我们可以获得一个脸谱的位图,但也可用相同的导航器和结构获得一个Face对象。
实际上我们常见到的文件资源管理器的实现完全可以使用生成器模式。由于时间关系,这里不再讲述。有可能在以后的模式中涉及到这些。