在软件的构建过程中,面临一个复杂对象的创建工作,每个部分的子对象都使用一定的算法构成。但是由于需求不断的变动,每个部分子对象的算法会随之而改变,但是整体的构建过程却保持相对的稳定性。在面向对象的设计过程中,如何应对这种变化?
比如在某个游戏场景中,需要构建一个房屋,构建房屋所需要的组件包括:窗户、屋顶、门、墙和地板。在一般的情况下,我们会这样去设计类之间的关系:
现在需求需要改变了,需要游戏添加一种新的场景——现代风格的房屋。这时候就将之前风格的窗户、屋顶、门、墙和地板都替换为现代的风格。这时候就面临着各种部件的变动,而相对的,房子整的构建过程不会改变,而且房子的构建过程比较复杂。上述的方案根本无法适应这种需求的改变,只能重新写BuildHouse类。那么我们应该如何的去设计类,尽可能的去复用房屋构建的算法(即不用重写BuildHouse),而不需要进行重新写?
在《设计模式》那本书中,提出了生成器的设计模式,该模式的意图就是将一个复杂对象的构建过程与其表示分离,是的相同的构建过程可以呈现不同的展示。这种设计模式恰好符合我们这种需求的变动,即复杂对象各个部分之间的变化。生成器模式类的结构图如下:
根据生成器模式,下面是重新设计的类:
1、首先是House部分的类,该部分是具体创建某一些组件的类。
1 public abstract class House { 2 /* abstract build the window */ 3 public abstract void buildWindow(); 4 5 /* abstract build the door */ 6 public abstract void buildDoor(); 7 8 /* abstract build the floor */ 9 public abstract void buildFloor(); 10 11 /* abstract build the Ceiling */ 12 public abstract void buildCeiling(); 13 14 /* abstract build the Wall */ 15 public abstract void buildWall(); 16 } 17 18 public class ClassicHouse extends House { 19 /* abstract build the window */ 20 public void buildWindow() {} 21 22 /* abstract build the door */ 23 public void buildDoor() {} 24 25 /* abstract build the floor */ 26 public void buildFloor() {} 27 28 /* abstract build the Ceiling */ 29 public void buildCeiling() {} 30 31 /* abstract build the Wall */ 32 public void buildWall() {} 33 } 34 35 public class ModenHouse extends House { 36 /* abstract build the window */ 37 public void buildWindow() {} 38 39 /* abstract build the door */ 40 public void buildDoor() {} 41 42 /* abstract build the floor */ 43 public void buildFloor() {} 44 45 /* abstract build the Ceiling */ 46 public void buildCeiling() {} 47 48 /* abstract build the Wall */ 49 public void buildWall() {} 50 }
2、其次是构建各个组块的类,该类的算法比较稳定,基本上不需要相应的变动。
1 public class BuildHouse { 2 House house; 3 4 public BuildHouse(House house) { 5 this.house = house; 6 } 7 8 /* 9 * 这部分是具体的创建房屋的算法,该部分的算法稳定性很高, 10 * 基本上不需要做过多的变动 11 */ 12 public House createHouse() { 13 house.buildFloor(); 14 15 house.buildWall(); 16 house.buildWall(); 17 house.buildWall(); 18 house.buildWall(); 19 20 house.buildWindow(); 21 house.buildWindow(); 22 23 house.buildDoor(); 24 25 house.buildCeiling(); 26 } 27 }
3、最后是一个简单的使用案例。
1 /* 一个简单的该模式的案例 */ 2 public class GameManager { 3 public static void main(String [] args) { 4 BuildHouse builder = new BuildHouse(new ClassicHouse()); 5 6 House house = builder.createHouse(); 7 } 8 }
上面就是生成器模式的基本概念和基本的使用。总体上来说,生成器模式还是比较易于理解的,这里需要进行区别的是要将生成器模式和前一节的抽象工厂模式进行区别开来。下面稍微总结一下生成器模式:
1、Builder主要是“分步骤构建一个复杂对象”,构造复杂对象的算法基本上是稳定的。
2、Abstract Factory主要解决一系列对象的变化,而Builder主要是“对象部分”的需求变化。对于Builder来说,在最后一步返回产品,而Abstract Factory是立即返回产品的。