作为一个新入职的魔导士呢,哦不,是程序员,我以为并没有太多机会去设计项目的软件架构。但是,工作一段时间之后,自己渐渐意识到,哪怕是自己要去做的小feature,也是需要去好好设计。我就应该做好它的架构师。看过一些牛人的文章后,总算意识到自己应该好好学习下设计模式。尽管并不是为了把设计模式作为教条式的方案套用到现实的工作中去,起码我也要做到心中有佛吧,...是心中有数,再在日后工作中积累经验,达到融汇贯通的境地。设计模式是前人总结出的相当重要的经验,也是针对特定问题的简洁而优雅的解决方案。我想,它们不仅在面向对象(OO)设计中极具参考价值,更能推广到日常生活方方面面。因此,我还是好好地学习下设计模式,在此记录自己的学习笔记。废话不多说,开始第一篇:Builder模式。
总觉得书上讲的例子会否太过严肃,我在这里还是祭出时の魔导士(Mage)的大杀器,神奇的“世界创造器”--WorldCreator吧!平行世界的概念想必大家都懂,现在让我们来看看,Mage如果要用咒语createWorld来生成一个平行世界,让可爱的白雪公主和7个霍比特人幸福快乐地生活,我们从哪开始呢?(貌似混进了奇怪的事情。)那就让我们从WorldCreator类开始吧,它定义了以下接口来创造世界:
1 class WorldCreator { 2 public: 3 virtual void createWorld() {} 4 virtual void createMountains(int m) {} 5 virtual void createPlants(int p) {} 6 virtual void createBuildings(int b) {} 7 virtual World* getWorld() { return 0; } 8 protected: 9 WorldCreator(); 10 };
首先建立一个平行世界,然后造山,造树,造房子,嗯......咦,怎么都是virtual?没错!WorldCreator就是前文所提的Builder,它自己并不实际用来创造世界,而是由它的子类来完成;它的主要目的仅仅是为创造世界提供接口,并且,这些接口缺省操作虽然是空,什么也不做,但也不定义成纯虚函数。因为这样便于子类只重定义它们所感兴趣的那些方法。比方说,我突然又想创造一个许多元素生物存在的世界,那里压根没有人工建筑Buildings,那么我就不用重写createBuildings方法了。后面会继续讲到。
有了WorldCreator,我们来看看Mage的createWorld咒语(圈内术语应该叫Mage类的createWorld成员函数)到底是什么样的吧:
1 World* Mage::createWorld(WorldCreator& builder) { 2 builder.createWorld(); 3 builder.createMountains(1); 4 builder.createPlants(100); 5 builder.createBuildings(8); 6 7 return builder.getWorld(); 8 }
像其他创建型模式一样,Builder模式封装了对象是如何被创建的,在这个例子中是通过WorldCreator所定义的接口来封装的。这就意味着我们的Mage可以重用WorldCreator来创造不同种类的世界,比方说,前面提到的没有人工建筑的世界:
1 World* Mage::createEarthElementalWorld(WorldCreator& builder) { 2 builder.createWorld(); 3 builder.createMountains(100); 4 5 return builder.getWorld(); 6 }
什么?连树都没有,这地方白雪公主可不想去。
前面说过WorldCreator本身并不能创造世界,因为它是虚的,它的子类才做了实际的工作。来看一个简单的子类LovelyWorldCreator实现:
1 class LovelyWorldCreator : public WorldCreator { 2 public: 3 LovelyWorldCreator() { _currentWorld = 0; } 4 5 virtual void createWorld(); 6 virtual void createMountains(int); 7 virtual void createPlants(int); 8 virtual void createBuildings(int); 9 10 virtual World* getWorld() { return _currentWorld; } 11 private: 12 World* _currentWorld; 13 }; 14 15 void LovelyWorldCreator::createWorld() { 16 _currentWorld = new World(); 17 } 18 19 void LovelyWorldCreator::createMountains(int m) { 20 if ( !_currentWorld->hasMountains(m) ) { 21 Mountains* mountains = new Mountains(m); 22 _currentWorld->addMountains(mountains); 23 } 24 } 25 26 void LovelyWorldCreator::createPlants(int p) { 27 if ( !_currentWorld->hasPlants(p) ) { 28 Plants* plants = new Plants(p); 29 _currentWorld->addPlants(plants); 30 } 31 } 32 33 void LovelyWorldCreator::createBuildings(int b) { 34 if ( !_currentWorld->hasBuildings(b) ) { 35 Buildings* buildings = new Buildings(b); 36 _currentWorld->addBuildings(buildings); 37 } 38 }
这里createWorld先创造了一个空的世界,然后createMountains, createPlants, createBuildings 分别为这可爱的世界添加了山、树以及建筑物。现在,Mage终于可以用createWorld和LovelyWorldCreator来创造一个平行世界了:
1 Mage I; 2 LovelyWorldCreator spell; 3 World* world = I.createWorld(spell);
美丽的白雪公主如愿以偿地住进了可爱的世界。当然,还有那些霍比特人们。
啊,对了,差点忘了说,正因为我们采用了Builder模式(似乎刚跑题了会,赶紧拉回来),将World的构建从World本身的构造函数中分离出来,由WorldCreator封装了统一的创造过程,但是却能通过子类比如LovelyWorldCreator等来创造不同表现形式。这正是Builder设计模式的特点之一。总结说来,Builder模式有如下几个特点:
今天的笔记就到这里了,欢迎大家批评指正!如果觉得可以的话,好文推荐一下,我会非常感谢的!
[学习笔记]设计模式之Builder,布布扣,bubuko.com
原文:http://www.cnblogs.com/xieziyu/p/3569489.html