知识点五: 建造者模式
一、概述
建造者模式(Builder Pattern),又被称为生成器模式,它属于23种GOF设计模式的创建型设计模式 ,它与工厂方法模式和抽象工厂模式不同,后两者的目的是为了实现多态性,而 建造者模式的目的则是为了将对象的构建与展示分离
。建造者模式是使用多个简单的对象一步一步构建成一个复杂的对象。 它允许用户在不知道内部构建细节的情况下,可以更精细地控制对象的构造流程。一个复杂的对象有大量的组成部分,比如汽车它有车轮、方向盘、发动机、以及各种各样的小零件,要将这些部件装配成一辆汽车,这个装配过程无疑会复杂,对于这种情况,为了实现在构建过程中对外部隐藏具体细节,就可以使用 Builder 模式将部件和组装过程分离,使得构建过程和部件都可以自由扩展,同时也能够将两者之间的耦合降到最低。
该模式用来隐藏复合对象的创建过程,它把复合对象的创建过程加以抽象,通过子类继承和重载的方式,动态地创建具有复合属性的对象。
二、优缺点及使用场景
优点:
- 建造者独立,易扩展。
- 便于控制细节风险。
缺点:
- 产品必须有共同点,范围有限制。
- 如内部变化复杂,会有很多的建造类。
使用场景
- 对象的创建:Builder模式是为对象的创建而设计的模式
- 创建的是一个复合对象:被创建的对象为一个具有复合属性的复合对象
- 关注对象创建的各部分的创建过程:不同的工厂(这里指builder生成器)对产品属性有不同的创建方法
三、模式中包含的角色和其职责以及模式实现方式
1、角色
抽象建造者(Builder)角色:给出一个抽象接口,以规范产品对象的各个组成成分的建造。这个接口规定要实现复杂对象的哪些部分的创建,并不涉及具体的对象部件的创建。
具体建造者(ConcreteBuilder)角色:实现Builder接口,针对不同的商业逻辑,具体化复杂对象的各部分的创建。 在建造过程完成后,提供产品的实例。
监工(Director)角色:调用具体建造者来创建复杂对象的各个部分,在指导者中不涉及具体产品的信息,只负责保证对象各部分完整创建或按某种顺序创建。
具体产品(Product)角色:要创建的复杂对象。
2、实现方式
建造者:创建和提供实例
监工:管理建造出来的实例的依赖关系。
四、在Java中的实现
1、抽象建造者
/**
* @Description: 抽象建造者
* @Author: Ling.D.S
* @Date: Created in 2018/11/7 20:03
*/
public interface HouseBuilder {
//建地板
public void buildFloor();
//建墙
public void buildWall();
//建屋顶
public void buildHousetop();
//交付(返回对象)
public House getProduct();
}
2、具体建造者
/**
* @Description: 修平房的工程队
* @Author: Ling.D.S
* @Date: Created in 2018/11/7 20:06
*/
public class PingFangBuilder implements HouseBuilder {
//修房子就要给个房子实例
House house = new House();
//房子(类)具体属性给各个建造工人(方法)去赋值
@Override
public void buildFloor() {
house.setFloor("平房---地板");
}
@Override
public void buildWall() {
house.setWall("平房---墙");
}
@Override
public void buildHousetop() {
house.setHousetop("平房---屋顶");
}
@Override
public House getProduct() {
return house;
}
}
3、监工
/**
* @Description: 监工
* @Author: Ling.D.S
* @Date: Created in 2018/11/7 20:20
*/
public class HouseDirector {
private HouseBuilder builder;
//使用构造给工程队赋值
public HouseDirector(HouseBuilder builder){
this.builder = builder;
}
//监工让工程队建房子
public void makeHouse(){
builder.buildFloor();
builder.buildHousetop();
builder.buildWall();
}
/* 大部分人都这么写,省资源
public void makeHouse(HouseBuilder builder){
builder.buildFloor();
builder.buildHousetop();
builder.buildWall();
}*/
}
4、具体产品
/**
* @Description: 房子
* @Author: Ling.D.S
* @Date: Created in 2018/11/7 19:54
*/
public class House {
//地板
private String floor;
//墙
private String wall;
//屋顶
private String housetop;
//提供set/get方法
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;
}
//方便看
@Override
public String toString() {
return "House{" +
"floor='" + floor + '\'' +
", wall='" + wall + '\'' +
", housetop='" + housetop + '\'' +
'}';
}
}
5、客户端
/**
* @Description: 客户端
* @Author: Ling.D.S
* @Date: Created in 2018/11/7 19:54
*/
public class MainClass {
/*public static void main(String[] args) {
//工程队来建房子
//实例化工程队
HouseBuilder pingFangBuilder = new PingFangBuilder();
//建房子 这里的还是客户让工程队来建 不方便 所以我们加入一个监工
pingFangBuilder.buildFloor();
pingFangBuilder.buildWall();
pingFangBuilder.buildHousetop();
//返回房子
House house = pingFangBuilder.getProduct();
System.out.println(house);
}*/
//有监工的方法
public static void main(String[] args) {
//先来一个工程队
HouseBuilder pingFangBuilder = new PingFangBuilder();
//在来一个监工,把工程队给监工管理
HouseDirector director = new HouseDirector(pingFangBuilder);
//监工让工程队建房子
director.makeHouse();
//工程队交付房子
House product = pingFangBuilder.getProduct();
System.out.println(product);
}
}
结果:
这时候我们要改需求,我们要建别墅,那么我们只要添加一个具体建造者
/**
* @Description: 这时候要想建别墅(新对象),只要换个建造者就好了
* @Author: Ling.D.S
* @Date: Created in 2018/11/7 20:30
*/
public class BieShuBuilder implements HouseBuilder {
House bieshu = new House();
@Override
public void buildFloor() {
bieshu.setFloor("别墅--地板");
}
@Override
public void buildWall() {
bieshu.setWall("别墅--墙");
}
@Override
public void buildHousetop() {
bieshu.setHousetop("别墅--屋顶");
}
@Override
public House getProduct() {
return bieshu;
}
}
修改客户端的一行代码
/**
* @Description: 客户端
* @Author: Ling.D.S
* @Date: Created in 2018/11/7 19:54
*/
public class MainClass {
/*public static void main(String[] args) {
//工程队来建房子
//实例化工程队
HouseBuilder pingFangBuilder = new PingFangBuilder();
//建房子 这里的还是客户让工程队来建 不方便 所以我们加入一个监工
pingFangBuilder.buildFloor();
pingFangBuilder.buildWall();
pingFangBuilder.buildHousetop();
//返回房子
House house = pingFangBuilder.getProduct();
System.out.println(house);
}*/
//有监工的方法
/*public static void main(String[] args) {
//先来一个工程队
HouseBuilder pingFangBuilder = new PingFangBuilder();
//在来一个监工,把工程队给监工管理
HouseDirector director = new HouseDirector(pingFangBuilder);
//监工让工程队建房子
director.makeHouse();
//工程队交付房子
House product = pingFangBuilder.getProduct();
System.out.println(product);
}*/
//新需求,建别墅
public static void main(String[] args) {
//我们只需换个工程队就好了
BieShuBuilder bieshuBuilder = new BieShuBuilder();
//在来一个监工,把工程队给监工管理
HouseDirector director = new HouseDirector(bieshuBuilder);
//监工让工程队建房子
director.makeHouse();
//工程队交付房子
House product = bieshuBuilder.getProduct();
System.out.println(product);
}
}
结果
转载请注明原地址,宋德凌的博客:http://CoderOfSong.github.io 谢谢!