“代码:https://github.com/nateshao/design-demo
复杂模式
分析:如何将这些部件组装成一辆完整的汽车并返回给用户?
建造者模式
“建造者模式可以将部件本身和它们的组装过程分开,关注如何一步步创建一个包含多个组成部分的复杂对象,用户只需要指定复杂对象的类型即可得到该对象,而无须知道其内部的具体构造细节。
定义
“建造者模式:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
对象创建型模式
建造者模式的结构
建造者模式包含以下4个角色:
Builder
(抽象建造者)ConcreteBuilder
(具体建造者)Product
(产品)Director
(指挥者)典型的复杂对象类代码:
public class Product {
private String partA; //定义部件,部件可以是任意类型,包括值类型和引用类型
private String partB;
private String partC;
//partA的Getter方法和Setter方法省略
//partB的Getter方法和Setter方法省略
//partC的Getter方法和Setter方法省略
}
典型的抽象建造者类代码:
public abstract class Builder {
//创建产品对象
protected Product product=new Product();
public abstract void buildPartA();
public abstract void buildPartB();
public abstract void buildPartC();
//返回产品对象
public Product getResult() {
return product;
}
}
典型的具体建造者类代码:
public class ConcreteBuilder1 extends Builder{
public void buildPartA() {
product.setPartA("A1");
}
public void buildPartB() {
product.setPartB("B1");
}
public void buildPartC() {
product.setPartC("C1");
}
}
典型的指挥者类代码:
public class Director {
private Builder builder;
public Director(Builder builder) {
this.builder=builder;
}
public void setBuilder(Builder builder) {
this.builder=builer;
}
//产品构建与组装方法
public Product construct() {
builder.buildPartA();
builder.buildPartB();
builder.buildPartC();
return builder.getResult();
}
}
客户类代码片段:
……
Builder builder = new ConcreteBuilder1(); //可通过配置文件实现
Director director = new Director(builder);
Product product = director.construct();
……
实例说明
某游戏软件公司决定开发一款基于角色扮演的多人在线网络游戏,玩家可以在游戏中扮演虚拟世界中的一个特定角色,角色根据不同的游戏情节和统计数据(例如力量、魔法、技能等)具有不同的能力,角色也会随着不断升级而拥有更加强大的能力。
作为该游戏的一个重要组成部分,需要对游戏角色进行设计,而且随着该游戏的升级将不断增加新的角色。通过分析发现,游戏角色是一个复杂对象,它包含性别、面容等多个组成部分,不同类型的游戏角色,其性别、面容、服装、发型等外部特性都有所差异,例如“天使”拥有美丽的面容和披肩的长发,并身穿一袭白裙;而“恶魔”极其丑陋,留着光头并穿一件刺眼的黑衣。
无论是何种造型的游戏角色,它的创建步骤都大同小异,都需要逐步创建其组成部分,再将各组成部分装配成一个完整的游戏角色。现使用建造者模式来实现游戏角色的创建。
实例类图
实例代码
Actor
:游戏角色类,充当复杂产品对象ActorBuilder
:游戏角色建造者,充当抽象建造者HeroBuilder
:英雄角色建造者,充当具体建造者AngelBuilder
:天使角色建造者,充当具体建造者DevilBuilder
:恶魔角色建造者,充当具体建造者ActorController
:角色控制器,充当指挥者Client
:客户端测试类结果及分析
<?xml version="1.0"?>
<config>
<className>designpatterns.builder.AngelBuilder</className>
</config>
省略Director:将Director和抽象建造者Builder合并
public abstract class ActorBuilder {
protected static Actor actor = new Actor();
public abstract void buildType();
public abstract void buildSex();
public abstract void buildFace();
public abstract void buildCostume();
public abstract void buildHairstyle();
public static Actor construct(ActorBuilder ab) {
ab.buildType();
ab.buildSex();
ab.buildFace();
ab.buildCostume();
ab.buildHairstyle();
return actor;
}
}
……
ActorBuilder ab;
ab = (ActorBuilder)XMLUtil.getBean();
Actor actor;
actor = ActorBuilder.construct(ab);
……
将construct()方法中的参数去掉,直接在construct()方法中调用buildPartX()方法
public abstract class ActorBuilder {
protected Actor actor = new Actor();
public abstract void buildType();
public abstract void buildSex();
public abstract void buildFace();
public abstract void buildCostume();
public abstract void buildHairstyle();
public Actor construct() {
this.buildType();
this.buildSex();
this.buildFace();
this.buildCostume();
this.buildHairstyle();
return actor;
}
}
……
ActorBuilder ab;
ab = (ActorBuilder)XMLUtil.getBean();
Actor actor;
actor = ab.construct();
……
钩子方法的引入
钩子方法(Hook Method):返回类型通常为boolean类型,方法名一般为isXXX()
ActorBuilder.java
public abstract class ActorBuilder {
protected Actor actor = new Actor();
public abstract void buildType();
public abstract void buildSex();
public abstract void buildFace();
public abstract void buildCostume();
public abstract void buildHairstyle();
//钩子方法
public boolean isBareheaded() {
return false;
}
public Actor createActor() {
return actor;
}
}
DevilBuilder.java
public class DevilBuilder extends ActorBuilder {
public void buildType() {
actor.setType("恶魔");
}
public void buildSex() {
actor.setSex("妖");
}
public void buildFace() {
actor.setFace("丑陋");
}
public void buildCostume() {
actor.setCostume("黑衣");
}
public void buildHairstyle() {
actor.setHairstyle("光头");
}
//覆盖钩子方法
public boolean isBareheaded() {
return true;
}
}
ActorController.java
public class ActorController {
public Actor construct(ActorBuilder ab) {
Actor actor;
ab.buildType();
ab.buildSex();
ab.buildFace();
ab.buildCostume();
//通过钩子方法来控制产品的构建
if(!ab.isBareheaded()) {
ab.buildHairstyle();
}
actor=ab.createActor();
return actor;
}
}
模式优点
模式缺点
模式适用环境