浅论建造者模式(Builder)

一、经典Builder模式
我们先来看下经典Builder模式,先上UML类图:
在这里插入图片描述

案例:建造汽车:
import java.util.*;
//建造汽车:
class Automobile extends ArrayList{ }
class Car extends Automobile { }
class Truck extends Automobile { }
class Bus extends Automobile { }
// 使用的汽车部件:发动机、轮胎、车厢
class Part
{
private String s;
public Part(String s){
this.s = s;
}
public String toString( ){
return s;
}
}
class Engine extends Part
{
public Engine(String s)
{
super(s);
}
}
class Tyre extends Part
{
public Tyre(String s)
{
super(s);
}
}
class Carriage extends Part
{
public Carriage(String s)
{
super(s);
}
}
// 抽象建造者角色,它规范了所有汽车建造的步骤:
interface Builder
{
public void buildBase( ); //建造车架
public void addAutomobileItem(Part item); //安装部件
public void checkAutomobileItem(Part item);//检查部件
public void testAutomobile( ); //整车调试
public Automobile getResult( );//整车完成
}

// 具体建造者角色
class CarBuilder implements Builder
{
private Car c;
public void buildBase()
{
System.out.println(“Building a Car framework”);
c = new Car( );
}
public void addAutomobileItem(Part item)
{
System.out.println("Adding Car part: " + item);
c.add(item);
}
public void checkAutomobileItem(Part item)
{
System.out.println("Checking Car part: " + item);
}
public void testAutomobile( )
{
System.out.println(“Car is testing! Bla,Bla,Bla…OK!”);
}
public Automobile getResult( ){
return c;
}
}
class TruckBuilder implements Builder
{
private Truck t;
public void buildBase()
{
System.out.println(“Building a Truck framework”);
t = new Truck( );
}
public void addAutomobileItem(Part item)
{
System.out.println("Adding Truck part: " + item);
t.add(item);
}
public void checkAutomobileItem(Part item)
{
System.out.println("Checking Truck part: " + item);
}
public void testAutomobile( )
{
System.out.println(“Truck is testing! Bla,Bla,Bla…OK!”);
}
public Automobile getResult( ){
return t;
}
}
class BusBuilder implements Builder
{
private Bus bus;
public void buildBase()
{
System.out.println(“Building a Bus framework”);
bus = new Bus( );
}
public void addAutomobileItem(Part item)
{
System.out.println(“Adding Bus part: " + item);
bus.add(item);
}
public void checkAutomobileItem(Part item)
{
System.out.println(“Checking Bus part: " + item);
}
public void testAutomobile( )
{
System.out.println(“Bus is testing! Bla,Bla,Bla…OK!”);
}
public Automobile getResult( ){
return bus;
}
}
// 指导者角色
class Director
{
private Builder b;
public Director(Builder b)
{
this.b = b; // 具有策略模式相似特征的
}
//下面for循环这里是step-by-step的,不同于Abstract Factory
public Automobile produceAuto(List input)
{
b.buildBase( );
for (Iterator it = input.iterator(); it.hasNext()😉
{
Part p=(Part)it.next( );
b.addAutomobileItem§;
b.checkAutomobileItem§;
}
b.testAutomobile( );
return b.getResult();
}
}
// 测试程序——客户端程序
public class BuildAutomobile
{
private List input = Arrays.asList(new Part[] {
new Engine(“Engine”), new Carriage(“Carriage”),
new Tyre(“Tyre”) });
public void testCar( )
{
Director buildCar = new Director(new CarBuilder());
Automobile car = buildCar.produceAuto(input);
String result = “Car: " + car;
System.out.println(result);
System.out.println(input);
System.out.println(”");
//assertEquals(result, “Car: [Engine, Carriage, Tyre]”);
}
public void testTruck()
{
Director buildTruck = new Director(new TruckBuilder());
Automobile tk = buildTruck.produceAuto(input);
String result = “Truck: " + tk;
System.out.println(result);
System.out.println(input);
System.out.println(”
”);
//assertEquals(result, “Truck: [Engine, Carriage, Tyre]”);
}
public void testBus()
{
Director buildBus = new Director(new BusBuilder());
Automobile bus = buildBus.produceAuto(input);
String result = “Bus: " + bus;
System.out.println(result);
System.out.println(input);
System.out.println(”======================”);
//assertEquals(result, “Bus: [Engine, Carriage, Tyre]”);
}
public static void main(String[] args)
{
BuildAutomobile a=new BuildAutomobile( );
a.testCar();
a.testTruck();
a.testBus();
//junit.textui.TestRunner.run(BuildAutomobile.class);
}
}
运行结果:
Building Car framework!!
Adding Car part: Engine
Checking Car part:Engine
Adding Car part: Carriage
Checking Car part:Carriage
Adding Car part: Tyre
Checking Car part:Tyre
Car is testing, Bla! Bla! Bla!
Car: [Engine, Carriage, Tyre]
[Engine, Carriage, Tyre]

Building Truck framework!!
Adding Truck part: Engine
Checking Truck part:Engine
Adding Truck part: Carriage
Checking Truck part:Carriage
Adding Truck part: Tyre
Checking Truck part:Tyre
Truck is testing, Bla! Bla! Bla!
Truck: [Engine, Carriage, Tyre]
[Engine, Carriage, Tyre]

Building Bus framework!!
Adding Bus part:Engine
Checking Bus part:Engine
Adding Bus part:Carriage
Checking Bus part:Carriage
Adding Bus part:Tyre
Checking Bus part:Tyre
Bus is testing, Bla! Bla! Bla!
Bus: [Engine, Carriage, Tyre]
[Engine, Carriage, Tyre]

二、变种Builder模式
今天项目经理突然跑过来扔了一个需求给你:需要创建一个不可变的Person对象,这个Person可以拥有以下几个属性:名字、性别、年龄、职业、车、鞋子、衣服、钱、房子。其中名字和性别是必须有的。我苦思冥想找到了解决办法,就是用下面这种变种的Builder模式:
public class Person {
/名字(必须)/
private final String name;
/性别(必须)/
private final String gender;
/年龄(非必须)/
private final String age;
/鞋子(非必须)/
private final String shoes;
/衣服(非必须)/
private final String clothes;
/钱(非必须)/
private final String money;
/房子(非必须)/
private final String house;
/汽车(非必须)/
private final String car;
/职业(非必须)/
private final String career;

private Person(Builder builder) {
    this.name = builder.name;
    this.gender = builder.gender;
    this.age = builder.age;
    this.shoes = builder.shoes;
    this.clothes = builder.clothes;
    this.money = builder.money;
    this.house = builder.house;
    this.car = builder.car;
    this.career = builder.career;
}
public static class Builder {
    private final String name;
    private final String gender;
    private String age;
    private String shoes;
    private String clothes;
    private String money;
    private String house;
    private String car;
    private String career;

    public Builder(String name,String gender) {
        this.name = name;
        this.gender = gender;
    }
    public Builder age(String age) {
        this.age = age;
        return this;
    }
    public Builder car(String car) {
        this.car = car;
        return this;
    }
    public Builder shoes(String shoes) {
        this.shoes = shoes;
        return this;
    }
    public Builder clothes(String clothes) {
        this.clothes = clothes;
        return this;
    }
    public Builder money(String money) {
        this.money = money;
        return this;
    }
    public Builder house(String house) {
        this.house = house;
        return this;
    }
    public Builder career(String career) {
        this.career = career;
        return this;
    }
    public Person build(){
        return new Person(this);
    }
}

由于这个Person对象是不可变的,所以毫无疑问我们给他的所有属性都加了final修饰,当然如果没有不可变的需求也是可以不加的,然后在Person类中定义一个内部类Builder,这个Builder内部类中的属性要和Person中的相同,并且必须有的属性要用final修饰,防止这些属性没有被赋值,其他非必须的属性不能用final,因为如果加了final,就必须对其进行初始化,这样这些非必须的属性又变成必须的。然后内部类中定义了一个构造方法,传入必须有的属性。其他非必须的属性都通过方法设置,每个方法都返回Builder对象自身。最后定义了一个build方法,将Builder对象传入Person的私有构造方法,最终返回一个对象。
接下来我们来看下Person的创建:
Person person = new Person.Builder(“织女星”,“天琴座-α”)
.age(“32”)
.money(“120000”)
.car(“宝马”)
.build();
是不是看上去逼格瞬间提高了,非必须的属性可以根据需要任意设置,非常灵活,而且这样先设置属性再创建对象,最终获取的对象一定是你预期的完整对象,不会像用之前set的方法创建的对象可能还没有设置完全。好了,写完之后,你迫不及待的把这个Person类提交给了Boss,果然Boss对这种对象创建方式非常满意。好了两种建造者模式到这也分析的差不多了,相信你对建造者模式有了更好的理解。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值