设计模式:建造者模式
建造者模式
维基百科上面的解释是:
建造模式,是一种对象构建模式。它可以将复杂对象的建造过程抽象出来(抽象类别),使这个抽象过程的不同实现方法可以构造出不同表现(属性)的对象。
应用场景
适用于当需要根据不同情形创建相同产品,但产品属性各异的情景。
实例
例如一款游戏中用户可以根据需要创建不同的游戏角色(Actor)。游戏角色暂时只有两种(后续可以扩展),人族(Human)和狼族(Wolf)。角色有三个属性,种族名(name)、职位(title)和性别(sex)。
角色类(Actor)
String name;
String title;
int sex;
void setName(String name);
void setTitle(String title);
void setSex(int sex);
抽象的角色创建类(ActorBuilder)包含角色(Actor),并设置角色的各个属性。并且提供方法返回这个角色。
void buildName();
void buildTitle();
void buildSex();
Actor createActor();
具体的创建类如人族创建类(HumanBuilder)实现或继承抽象的角色创建类(ActorBuilder)。
void buildName(){
actor.setName("Human");
}
void buildTitle(){
actor.setTitle("Lord");
}
void buildSex(){
actor.setSex(1);
}
Actor createActor(){
return actor;
}
角色创建控制器(ActorController)定义角色属性的创建次序,并返回角色给调用者(客户端)。
Actor construct(ActorBuilder builder){
builder.buildName();
builder.buildTitle();
builder.buildSex();
return builder.createActor();
}
演示代码
Actor.java
public class Actor{
private String name;
private String title;
private int sex;
public void setName(String name){
this.name = name;
}
public void setTitle(String title){
this.title = title;
}
public void setSex(int sex){
this.sex = sex;
}
public String getName(){
return name;
}
public String getTitle(){
return title;
}
public int getSex(){
return sex;
}
public String toString(){
return "name:" + name + ", title:" + title + ", sex:" + (sex==0?"Female":"Male");
}
}
ActorBuilder.java
interface ActorBuilder{
Actor actor = new Actor();
void buildName();
void buildTitle();
void buildSex();
Actor createActor();
}
HumanBuilder.java
public class HumanBuilder implements ActorBuilder{
public void buildName(){
actor.setName("Human");
}
public void buildTitle(){
actor.setTitle("Lord");
}
public void buildSex(){
actor.setSex(1);
}
public Actor createActor(){
return actor;
}
}
WolfBuilder.java
public class WolfBuilder implements ActorBuilder{
public void buildName(){
actor.setName("Wolf");
}
public void buildTitle(){
actor.setTitle("Ghost");
}
public void buildSex(){
actor.setSex(0);
}
public Actor createActor(){
return actor;
}
}
ActorController.java
public class ActorController{
public Actor construct(ActorBuilder builder){
builder.buildName();
builder.buildTitle();
builder.buildSex();
return builder.createActor();
}
}
builder.properties
#className=HumanBuilder
className=WolfBuilder
PropertyUtil.java
import java.io.*;
import java.util.*;
public class PropertyUtil{
public static Object getBean(){
Object obj = null;
try{
Properties prop = new Properties();
InputStream in = new BufferedInputStream(new FileInputStream("builder.properties"));
prop.load(in);
String className = prop.getProperty("className");
Class c = Class.forName(className);
obj = c.newInstance();
}catch(Exception e){
//Exception
e.printStackTrace();
}
return obj;
}
}
Client.java
public class Client{
public static void main(String args[]){
ActorBuilder builder = (ActorBuilder)PropertyUtil.getBean();
ActorController controller = new ActorController();
Actor actor = controller.construct(builder);
System.out.print(actor.toString());
}
}
扩展
简化后的控制类
如果简化结构,可以将角色创建控制类(ActorController)和抽象角色创建类(ActorBuilder)合并。在抽象角色创建类中指定角色属性的创建次序并返回角色。
abstract class ActorBuilder{
Actor actor = new Actor();
void buildName();
void buildTitle();
void buildSex();
Actor construct(){
this.buildName();
this.buildTitle();
this.buildSex();
return actor;
}
}
钩子的使用
有时我们需要更精细的控制产品的创建过程,这时可以使用一种特殊的方法(钩子方法)去控制某方法是否能够被调用(属性是否能被设置)。例如:对于狼族(Wolf)而言没有职位(tile)的说法。可以在抽象角色创建类(ActorBuilder)中加入钩子方法(boolean isOfficer())。在具体的儿狼族角色创建类(WolfBuilder)中覆盖钩子方法。
abstract class ActorBuilder{
Actor actor = new Actor();
void buildName();
void buildTitle();
void buildSex();
boolean isOfficer(){
return true;
}
Actor construct(){
this.buildName();
if(this.isOfficer()){
this.buildTitle();
}
this.buildSex();
return actor;
}
}
public class WolfBuilder implements ActorBuilder{
public void buildName(){
actor.setName("Wolf");
}
public void buildTitle(){
actor.setTitle("Ghost");
}
public void buildSex(){
actor.setSex(0);
}
public boolean isOfficer(){
return false;
}
}
改进后的代码演示
- ActorBuilder.java
abstract class ActorBuilder{
Actor actor = new Actor();
abstract void buildName();
abstract void buildTitle();
abstract void buildSex();
boolean isOfficer(){
return true;
}
Actor construct(){
this.buildName();
if(this.isOfficer()){
this.buildTitle();
}
this.buildSex();
return actor;
}
}
- HumanBuilder.java
public class HumanBuilder extends ActorBuilder{
public void buildName(){
actor.setName("Human");
}
public void buildTitle(){
actor.setTitle("Lord");
}
public void buildSex(){
actor.setSex(1);
}
}
- WolfBuilder.java
public class WolfBuilder extends ActorBuilder{
public void buildName(){
actor.setName("Wolf");
}
public void buildTitle(){
actor.setTitle("Ghost");
}
public void buildSex(){
actor.setSex(0);
}
public boolean isOfficer(){
return false;
}
}
- Client.java
public class Client{
public static void main(String args[]){
ActorBuilder builder = (ActorBuilder)PropertyUtil.getBean();
Actor actor = builder.construct();
System.out.print(actor.toString());
}
}
(完)