设计模式学习之Builder模式
这篇随笔的关注点是Builder(创建者、生成器)模式:适用的场景是产品局部加工变化较大,但是组装过程相对固定。创建者模式和工厂模式有点类似,不过关注点不同。工厂模式往往只关心你要的是什么,而创建模式则关心的是这个东西的具体细节的创建。例如:
- 攒机。尽管上网本、游戏PC的形态、功能相差比较大,但是它们都有必须的主板、内存、硬盘、显示器、外设等不同的元件,而且组装工程相对固定
- 搭建简单的门户网站。导航条、搜索框、页面主体、页脚的设计和实现千差外别,但是它们都经过类似的组装过程,最终形成Web Site
网上找了一张图,很好的表示了经典创建者模式的静态结构,其中包含3个角色:
- Director:指导产品的加工步骤,但指导完全基于Builder的抽象方法
- Builder:描述创建一个产品各个组成部分的抽象类
- ConcreteBuilder:实现Builder要求的内容,提供一个获得最终产品的方法
最终加工的产品类型并没有统一抽象为IProduct接口,主要原因是经过不同的ConcreteBuilder加工后的产品产别性对比较大,没必要给一个公共的基准抽象对象。针对特定类型的产品,设计特定的ConcreteBuilder。
下面直接上例子吧,需求如下:
- 制造一些交通工具,具备轮子和车灯
- 汽车:前后各2个轮子(共4个),前后各2个车灯(共4个);自行车:前后轮(共2个),无车灯(null)
定义目标产品
1 public class Vehicle
2 {
3 public IEnumerable<string> Wheels { get; set; }
4 public IEnumerable<string> Lights { get; set; }
5 }
2 {
3 public IEnumerable<string> Wheels { get; set; }
4 public IEnumerable<string> Lights { get; set; }
5 }
定义抽象创建者类型
1 public abstract class VehicleBuilderBase
2 {
3 public Vehicle Vehicle { get; protected set; }
4 public virtual void Create() { Vehicle = new Vehicle(); }
5 public abstract void AddWheels();
6 public abstract void AddLights();
7 }
2 {
3 public Vehicle Vehicle { get; protected set; }
4 public virtual void Create() { Vehicle = new Vehicle(); }
5 public abstract void AddWheels();
6 public abstract void AddLights();
7 }
定义具体的创建者类型
1 public class CarBuilder:VehicleBuilderBase
2 {
3 public override void AddWheels()
4 {
5 Vehicle.Wheels = new string[] { "front1", "front2", "back1", "back2" };
6 }
7
8 public override void AddLights()
9 {
10 Vehicle.Lights = new string[] { "front1", "front2", "back1", "back2" };
11 }
12 }
2 {
3 public override void AddWheels()
4 {
5 Vehicle.Wheels = new string[] { "front1", "front2", "back1", "back2" };
6 }
7
8 public override void AddLights()
9 {
10 Vehicle.Lights = new string[] { "front1", "front2", "back1", "back2" };
11 }
12 }
1 class BicycleBuilder:VehicleBuilderBase
2 {
3 public override void AddWheels()
4 {
5 Vehicle.Wheels = new string[] { "front", "back" };
6 }
7
8 public override void AddLights()
9 {
10 Vehicle.Lights = null;
11 }
12 }
2 {
3 public override void AddWheels()
4 {
5 Vehicle.Wheels = new string[] { "front", "back" };
6 }
7
8 public override void AddLights()
9 {
10 Vehicle.Lights = null;
11 }
12 }
定义产品生产指导类
1 public class VehicleBuilderDirector
2 {
3 public VehicleBuilderBase Builder { get; set; }
4 public Vehicle Vehicle { get { return Builder.Vehicle; } }
5
6 public void Construct()
7 {
8 Builder.Create();
9 Builder.AddLights();
10 Builder.AddWheels();
11 }
12 }
2 {
3 public VehicleBuilderBase Builder { get; set; }
4 public Vehicle Vehicle { get { return Builder.Vehicle; } }
5
6 public void Construct()
7 {
8 Builder.Create();
9 Builder.AddLights();
10 Builder.AddWheels();
11 }
12 }
单元测试
1 [TestMethod()]
2 public void BuildUpTest()
3 {
4 var director = new VehicleBuilderDirector();
5 director.Builder = new CarBuilder();
6 director.Construct();
7 Assert.AreEqual<int>(4, director.Vehicle.Wheels.Count());
8 Assert.AreEqual<int>(4, director.Vehicle.Lights.Count());
9
10 director.Builder = new BicycleBuilder();
11 director.Construct();
12 Assert.AreEqual<int>(2, director.Vehicle.Wheels.Count());
13 Assert.IsNull(director.Vehicle.Lights);
14 }
2 public void BuildUpTest()
3 {
4 var director = new VehicleBuilderDirector();
5 director.Builder = new CarBuilder();
6 director.Construct();
7 Assert.AreEqual<int>(4, director.Vehicle.Wheels.Count());
8 Assert.AreEqual<int>(4, director.Vehicle.Lights.Count());
9
10 director.Builder = new BicycleBuilder();
11 director.Construct();
12 Assert.AreEqual<int>(2, director.Vehicle.Wheels.Count());
13 Assert.IsNull(director.Vehicle.Lights);
14 }
到目前为止,目标已经初步实现了,但是创建者模式暴露出较多的执行步骤,Director(Client)需要较多的领域知识,很容易造成高耦合。
作者:Hans Huang
出处:http://www.cnblogs.com/Hans2Rose/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。
出处:http://www.cnblogs.com/Hans2Rose/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。