答案: 第四章 生成器(Builder)
1. 意图
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
2. 分类
创建型模式。
3. 问题是什么?
在抽象工厂一章中,我们了解到了在全球建房系统中如何支持多种房屋的风格。新的问题是:用户希望看到同样结构下,不同风格房屋的外观。比如:这个房子有一个地板,一个天花板,四面墙,一个门,一个窗户。他希望看到中国风格房屋和希腊风格房屋的相应式样。
4. 解决方法
1) 创建一个生成器(Buider)类:Class HouseBuider
{
BuildHouse(){}
BuildWall(int){}
BuildDoor(int){}
BuildWindow(int) {}
BuildFloor(){}
BuildCeiling() {}
BuildPillar(){}
GetHouse() { return Null;}
}
在这个类中,我们对每一种房屋组成元素都定义了一个Build方法。并且定义了一个返回构造结果的方法GetHouse。
2) 对每一种风格都定义一个具体的生成器(Concrete Builder)类:ChinaHouseBuilder: HouseBuilder
GreeceHouseBuilder: HouseBuilder
…
并且在这些类中重载父类的方法。
3) 还有,各种类型的房屋类:ChinaHouse
GreeceHouse
…
5. 如何使用
我们可以用下面的方法使用上面的类来解决我们的问题。Class HosueSystem
{
object Create( builder HouseBuilder)
{
builder.BuildHouse();
builder.BuildFloor();
builder.BuildCeiling();
builder.BuildWall(1);
builder.BuildWall(2);
builder.BuildWall(3);
builder.BuildWall(4);
builder.Door(1);// 在Wall1上建一个门
builder.Window(2); // 在Wall2上建一个窗户
return builder.GetHouse();
}
}
只要向通过HouseSystem.Create方法传入不同的生成器就可以得到不同风格的结果。
事实上,HouseSystem也是生成器模式的一个参与者,叫做导向者(Director)。注意的问题: ● 生成器(HouseBuilder)类中要包含每一种构件元素的生成方法。比如:楼梯这个元素在某些建筑风格中没有,在其他风格中有,也要加上BuilderStair方法在HouseBuilder中。
● 生成器(HouseBuilder)类不是抽象类,它的每一个生成方法一般情况下什么都不做。这样,具体生成器就不必考虑和它无关的元素的生成方法。
6. 杂谈
1) 也许你有这样的想法:生成器模式似乎过于复杂,可以直接在具体House类中定义CreateHouse方法就可以了,例如:Class ChinaHouse
{
ChinaHouse CreateHouse()
{ChinaHouse house;
house = new ChinaHouse();
house.Add(new Floor());
house.Add(new Ceiling());
house.Add(new Wall(1));
house.Add(new Wall(2));
house.Add(new Wall(3));
house.Add(new Wall(4));
house.Add(new Door(1));// 在Wall1上建一个门
house.Add(new Window(2)); // 在Wall2上建一个窗户
return house;
}
}
而生成器模式至少用了两个类来解决这个问题:导向者类和具体生成器类。
那么,生成器模式好在哪里?答案就是职责分配。生成器模式将一个复杂对象的生成这一职责作了一个很好的分配。它把构造过程放到导向者的方法中,把装配过程放到具体生成器类中。我们看看下面的说明。
2) HouseSystem类(导向者)可以非常精细的来构造House。而这个生成过程,对于产品类(ChinaHouse, GreeceHouse …)和生成器类 (ChinaHouseBuilder, GreeceHouseBuilder)都没有必要关心。具体生成器类则考虑装配元素的问题。
7. 活用
生成器模式可以应用在以下的问题上: ● 将系统的文档格式转换到其他的格式上(每一种格式的文档都相当于一个产品)。
● 编译问题(语法分析器是导向者,编译结果是产品)。
本文未经作者许可,严禁转载,违者必究!
关于作者:
杨宁是GrapeCity公司海外应用开发部技术骨干。从事多年的程序开发,有Unix,Windows平台上的开发经验。对VB,C#, VB.Net,XML有比较丰富的认识。喜爱研究OO的编程,分析,设计,项目管理等相关技术。喜欢学习新的技术。
上一个:架构设计中的方法学(7)——组合使用模式(1)
下一个:架构设计中的方法学(6)——迭代设计(1)