什么是建造者模式

Builder模式也叫建造者模式或者生成器模式,是由GoF提出的23种设计模式中的一种。Builder模式是一种对象创建型模式之一,用来隐藏复合对象的创建过程,它把复合对象的创建过程加以抽象,通过子类继承和重载的方式,动态地创建具有复合属性的对象。

首先我们建立一个House对象

package com.meritit;
/**
* 房子
* @author 李小强
*
*/
public class House {
//地板
private String floor;
//墙
private String wall;
//屋顶
private String housetop;

public String getFloor() {
return floor;
}
public void setFloor(String floor) {
this.floor = floor;
}
public String getWall() {
return wall;
}
public void setWall(String wall) {
this.wall = wall;
}
public String getHousetop() {
return housetop;
}
public void setHousetop(String housetop) {
this.housetop = housetop;
}


}


如果按照普通方法,我们去这样建造房子

package com.meritit;
/**
*
* @author 李小强
*
*/
public class MainClass {
public static void main(String[] args) {
//客户直接造房子
House house = new House();
house.setFloor("地板");
house.setHousetop("屋顶");
house.setWall("墙");
}
}


上面的这种方式实际上是让客户自己造房子,这显然不好,下面我们开始用建造者模式实现:

创建一个HouseBuilder接口

package com.meritit;
/**
* 造房子的接口
* @author 李小强
*
*/
public interface HouseBuilder {
//修地板
public void makeFloor();
//修墙
public void makeWall();
//修屋顶
public void makeHousetop();
//获得房子
public House getHouse();
}


用具体的造房子的工程实现

package com.meritit;
/**
* 平房工程队
* @author 李小强
*
*/
public class PingFangBuilder implements HouseBuilder{
House house = new House();

@Override
public void makeFloor() {
house.setFloor("平房地板");

}

@Override
public void makeWall() {
house.setWall("平房房顶");
}

@Override
public void makeHousetop() {
house.setHousetop("平房屋顶");
}

@Override
public House getHouse() {
return house;
}

}


现在这样造房子

package com.meritit;
/**
*
* @author 李小强
*
*/
public class MainClass {
public static void main(String[] args) {
//由工程队来修房子
HouseBuilder builder = new PingFangBuilder();
builder.makeFloor();
builder.makeHousetop();
builder.makeWall();
House house = builder.getHouse();

System.out.println(house.getFloor());
System.out.println(house.getHousetop());
System.out.println(house.getWall());
}
}


这里好像缺少一个专门建造房子的角色,下面我们这样做:

创建一个实际的建造者去造房子

package com.meritit;
/**
* 实际建造者
* @author 李小强
*
*/
public class HouseDicrector {

private HouseBuilder builder;

public HouseDicrector(HouseBuilder builder){
this.builder = builder;
}

/**
* 建造房子
*/
public void makeHouse(){
builder.makeFloor();
builder.makeHousetop();
builder.makeWall();
}
}


现在Main方法中就可以这样造房子了:

package com.meritit;

import javax.naming.directory.DirContext;

/**
*
* @author 李小强
*
*/
public class MainClass {
public static void main(String[] args) {
//设计房子
HouseBuilder builder = new PingFangBuilder();
//创造工程队
HouseDicrector dicrector = new HouseDicrector(builder);
//开始造
dicrector.makeHouse();
//得到房子
House house = builder.getHouse();

System.out.println(house.getFloor());
System.out.println(house.getHousetop());
System.out.println(house.getWall());
}
}


这就是建造者设计模式,如果现在你想建造公寓只需要先设计一个公寓就行。

设计公寓

package com.meritit;
/**
* 设计公寓
* @author 李小强
*
*/
public class GongyuBuilder implements HouseBuilder{
House house = new House();
@Override
public void makeFloor() {
house.setFloor("公寓地板");
}

@Override
public void makeWall() {
house.setWall("公寓墙");
}

@Override
public void makeHousetop() {
house.setHousetop("公寓房顶");
}

@Override
public House getHouse() {
return house;
}

}


在Main方法中只需将Pingfang平房改为Gongyu

package com.meritit;

import javax.naming.directory.DirContext;

/**
*
* @author 李小强
*
*/
public class MainClass {
public static void main(String[] args) {
//设计房子
HouseBuilder builder = new GongyuBuilder();
//创造工程队
HouseDicrector dicrector = new HouseDicrector(builder);
//开始造
dicrector.makeHouse();
//得到房子
House house = builder.getHouse();


System.out.println(house.getFloor());
System.out.println(house.getHousetop());
System.out.println(house.getWall());
}
}


 我们还可以再改一下

package com.meritit;
/**
* 实际建造者
* @author 李小强
*
*/
public class HouseDicrector {
/**
* 建造房子
*/
public void makeHouse(HouseBuilder builder){
builder.makeFloor();
builder.makeHousetop();
builder.makeWall();
}
}


这样在Main方法中可以这样做:

package com.meritit;

import javax.naming.directory.DirContext;

/**
*
* @author 李小强
*
*/
public class MainClass {
public static void main(String[] args) {
//设计房子
HouseBuilder builder = new GongyuBuilder();
//创造工程队
HouseDicrector dicrector = new HouseDicrector();
//开始造
dicrector.makeHouse(builder);
//得到房子
House house = builder.getHouse();


System.out.println(house.getFloor());
System.out.println(house.getHousetop());
System.out.println(house.getWall());
}
}


建造者模式的结构如图:

设计模式——建造者模式_建造者 

 建造者模式的应用场景:

-对象的创建:Builder模式是为对象的创建而设计的模式

- 创建的是一个复合对象:被创建的对象为一个具有复合属性的复合对象

- 关注对象创建的各部分的创建过程:不同的工厂(这里指builder生成器)对产品属性有不同的创建方法

建造者模式的优点:

        首先,建造者模式的封装性很好。使用建造者模式可以有效的封装变化,在使用建造者模式的场景中,一般产品类和建造者类是比较稳定的,因此,将主要的业务逻辑封装在导演类中对整体而言可以取得比较好的稳定性。

        其次,建造者模式很容易进行扩展。如果有新的需求,通过实现一个新的建造者类就可以完成,基本上不用修改之前已经测试通过的代码,因此也就不会对原有功能引入风险。

 建造者模式与工厂模式的区别:

       我们可以看到,建造者模式与工厂模式是极为相似的,总体上,建造者模式仅仅只比工厂模式多了一个“导演类”的角色。在建造者模式的类图中,假如把这个导演类看做是最终调用的客户端,那么图中剩余的部分就可以看作是一个简单的工厂模式了。

       与工厂模式相比,建造者模式一般用来创建更为复杂的对象,因为对象的创建过程更为复杂,因此将对象的创建过程独立出来组成一个新的类——导演类。也就是说,工厂模式是将对象的全部创建过程封装在工厂类中,由工厂类向客户端提供最终的产品;而建造者模式中,建造者类一般只提供产品类中各个组件的建造,而将具体建造过程交付给导演类。由导演类负责将各个组件按照特定的规则组建为产品,然后将组建好的产品交付给客户端。

总结

       建造者模式与工厂模式类似,他们都是建造者模式,适用的场景也很相似。一般来说,如果产品的建造很复杂,那么请用工厂模式;如果产品的建造更复杂,那么请用建造者模式。