建造者模式
GOF给建造者模式的定义是:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
来看看建造者模式的组成:
1.产品角色:建造中的复杂对象、它要包含哪些定义组件的类,包括将这些组件装配成产品的接口。
2.抽象建造者角色:这个角色用来规范产品对象的各个组成成分的建造。一般而言,此角色独立于应用程序的业务逻辑。
3.具体建造者角色:担任这个角色的是与应用程序紧密相关的类,它们在指导者的调用下创建产品实例。这个角色在实现抽象角色提供的方法的前提下,达到完成产品组装,提供成品的功能。
4.指导者角色:调用具体建造者角色以创建产品对象。指导者并没有产品类的具体知识,真正拥有产品类的具体知识是具体建造者对象。
来看看这些角色组成的类图:
建造者模式和工厂方法模式都是创建模式。下面通过代码来讲解来熟悉建造者模式:
产品角色:
1 package com.bluemsun.BuilderModel; 2 3 4 /** 5 * 产品类,一个Person的产品模型 6 * @author zhouxy 7 * 8 */ 9 public class PersonModel { 10 private Body body; 11 private Soul soul; 12 13 public Body getBody() { 14 return body; 15 } 16 public void setBody(Body body) { 17 this.body = body; 18 } 19 public Soul getSoul() { 20 return soul; 21 } 22 public void setSoul(Soul soul) { 23 this.soul = soul; 24 } 25 @Override 26 public String toString() { 27 return "Person ["+body.toString()+","+soul.toString()+"]"; 28 } 29 }
产品角色中body,soul组件的定义如下:
1 package com.bluemsun.BuilderModel; 2 3 public class Body { 4 private int eyes; 5 private int ear; 6 private int nose; 7 private int mouse; 8 private int hand; 9 private int leg; 10 11 /*此处省略setter,getter方法*/ 12 13 public Body(int eyes, int ear, int nose, int mouse, int hand, int leg) { 14 super(); 15 this.eyes = eyes; 16 this.ear = ear; 17 this.nose = nose; 18 this.mouse = mouse; 19 this.hand = hand; 20 this.leg = leg; 21 } 22 @Override 23 public String toString() { 24 return "Body [eyes=" + eyes + ", ear=" + ear + ", nose=" + nose 25 + ", mouse=" + mouse + ", hand=" + hand + ", leg=" + leg + "]"; 26 } 27 }
1 package com.bluemsun.BuilderModel; 2 3 public class Soul { 4 private String soul_type; 5 6 /*此处省略setter,getter方法*/ 7 public Soul(String soul_type) { 8 super(); 9 this.soul_type = soul_type; 10 } 11 @Override 12 public String toString() { 13 return "Soul [soul_type=" + soul_type + "]"; 14 } 15 }
抽象建造者角色:
1 package com.bluemsun.BuilderModel; 2 3 /** 4 * 抽象建造者接口,指明建造一个Person产品需要的组件(方法) 5 * @author zhouxy 6 * 7 */ 8 public interface Builder{ 9 10 public void buildBody();//构建body组件 11 public void buildSoul();//构建soul组件 12 13 public PersonModel getPersonModel();//通过上面两个组件的完成,在这里将组件组装,返回成品对象 14 }
具体建造者角色:
1 package com.bluemsun.BuilderModel; 2 3 /** 4 * 具体建造者类,实现Builder 5 * @author zhouxy 6 * 7 */ 8 public class PersonBuilder implements Builder{ 9 private PersonModel personModel = new PersonModel();//创建一个待组装的对象 10 11 @Override 12 public void buildBody() { //生产真正组件 13 Body body = new Body(2, 2, 1, 1, 2, 1); 14 personModel.setBody(body); 15 } 16 17 @Override 18 public void buildSoul() { //生产真正组件 19 Soul soul = new Soul("高尚的"); 20 personModel.setSoul(soul); 21 } 22 23 @Override 24 public PersonModel getPersonModel() { //将上面实际产生的组件进行组装 25 return personModel; //返回成品 26 } 27 }
指导者角色:
1 package com.bluemsun.BuilderModel; 2 3 4 /** 5 * 指导者.指导者根据不同的builder指导创建不同成品 6 * @author zhouxy 7 * 8 */ 9 public class Director { 10 private Builder builder; 11 12 public Director(Builder builder){ 13 this.builder = builder; 14 } 15 16 public void construct(){ //根据客户端提供的builder产生与builder对应的组件 17 builder.buildBody(); 18 builder.buildSoul(); 19 } 20 }
客户端代码:
1 package com.bluemsun.BuilderModel; 2 3 4 /** 5 * 客户端代码 6 * @author zhouxy 7 * 8 */ 9 public class Client { 10 public static void main(String[] args) { 11 Builder builder = new PersonBuilder(); 12 Director director = new Director(builder); 13 director.construct(); 14 PersonModel personModel = builder.getPersonModel(); 15 16 System.out.println(personModel.toString()); 17 18 /*builder = new SuperManBuilder(); 19 director = new Director(builder); 20 director.construct(); 21 personModel = builder.getPersonModel(); 22 23 System.out.println(personModel.toString());*/ 24 } 25 }
在客户端代码中,我们创建了一个具体建造者对象,并把这个对象交给指导者,指导者将会根据它的信息指导创建具体产品实例。如果现在我们需要创建另外一种产品实例,我们仅仅需要定义这种产品具体实现(代码如下),其他部分的代码不需要修改,客户端也仅仅只是需要增加上面注释部分的代码即可。
1 package com.bluemsun.BuilderModel; 2 3 /** 4 * 另一种具体产品的实现 5 * @author zhouxy 6 * 7 */ 8 9 public class SuperManBuilder implements Builder { 10 11 private PersonModel personModel = new PersonModel(); 12 13 @Override 14 public void buildBody() { 15 Body body = new Body(4, 4, 2, 2, 4, 4); 16 personModel.setBody(body); 17 } 18 19 @Override 20 public void buildSoul() { 21 Soul soul = new Soul("善良的,伟大的"); 22 personModel.setSoul(soul); 23 } 24 25 @Override 26 public PersonModel getPersonModel() { 27 28 return personModel; 29 } 30 31 }
建造模式的优点:
1.建造者模式可以使得产品内部的表象独立变化。在原来的工厂方法模式中,产品内部的表象是由产品自身来决定的,而在建造者模式中则是“外部化”为由具体的建造者来负责。这样定义一个新的具体建造者角色(就像上面的SuperManBuilder)就可以改变产品的内部表象,符合“开闭原则”。
2.建造者模式使得客户端不需要知道太多产品内部的细节。他将复杂对象的组件和表示方式封装在一个具体的建造角色中,而且由指导者类协调建造者角色来得到具体产品实例。