一.定义
- 将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。
二.作用
- 使类独立,易扩展,容易控制。
- 使类的创建过程更加清晰,简单。
三.案例
故事背景:某上市公司的达摩院,需要招技术工程师,那么需要招那些技术呢?是Java还是Html5呢?
不同情况可能还不一样前期可能先招个Java过来把后台搞一搞,数据库表结构设计设计。等到后台搭建的差不多了,那就再招一个前端把数据展示展示,再过段随着业务的扩大,目前的人员配置不够了,需要扩招Java,Html人才都需要。也有的公司项目比较急,一开始就会把人员配齐,或者招一部分的都有。说了这么多其实想说的就是,不同公司招人的顺序不一样。这也是建造者模式中很重要的一点,顺序不同结果也不同
3.1实现
以公司招技术人员来例,也不是什么人都需要,对技术人员是有要求的,是要有经验的,过来就能干活,技术类型可以分为Java和Html5,Java的可以作为服务端(Server)他们是Java工程师,Html5的可以作为前端(Web)他们是前端工程师
然后对招聘要求(Requirement),针对不同岗位做不同实现,工作类型抽象成Job接口,由人事部门负责收集不同的招聘要求(List
3.2步骤
1.创建招聘需求接口,和技术类型接口。
public interface Requirement {
//数量
int number();
//技术类型
Job job();
//工作年限
int years();
}
public interface Job {
String job();
}
2.技术类型job的实现类Java和Html5
public class Java implements Job{
@Override
public String job() {
return "Java工程师";
}
}
public class Html5 implements Job {
@Override
public String job() {
return "前端工程师";
}
}
3.服务端Server和Web前端作为一个抽象类去实现招聘需求(Requirement)并实现里面的Job方法
public abstract class Server implements Requirement {
@Override
public Job job() {
return new Java();
}
}
public abstract class Web implements Requirement {
@Override
public Job job() {
return new Html5();
}
}
4.Java工程师(JavaEngineer)扩展服务端(Server),Web工程师(WebEngineer)扩展Web前端
public class JavaEngineer extends Server {
@Override
public int number() {
return 5;
}
@Override
public int years() {
return 10;
}
}
public class WebEngineer extends Web {
@Override
public int number() {
return 1;
}
@Override
public int years() {
return 10;
}
}
5.人事部门收集其他部门招聘需求,制定招聘计划
//人事部门
public class Personnel {
private List mRequirements = new ArrayList<>();
public void addItem(Requirement item){
mRequirements.add(item);
}
//总人数
public int totalCount(){
int total = 0;
for (Requirement Requirement : mRequirements) {
total += Requirement.number();
}
return total;
}
//发布招聘
public void push(){
System.out.println("本公司开始招人了");
for (Requirement Requirement : mRequirements) {
System.out.print(Requirement.number()+"个");
System.out.print( Requirement.job().job());
System.out.println("要求工作年限"+ Requirement.years()+"年");
}
}
}
6.PersonnelBuilder属于一个封装类也可以说是一个建造者,建造的顺序不同结果也不同。
public class PersonnelBuilder {
//招Java
public Personnel javaBuilder() {
Personnel per = new Personnel();
per.addItem(new JavaEngineer());
return per;
}
//招Html5
public Personnel htmlBuilder() {
Personnel per = new Personnel();
per.addItem(new WebEngineer());
return per;
}
//同时需要
public Personnel builder() {
Personnel per = new Personnel();
per.addItem(new JavaEngineer());
per.addItem(new WebEngineer());
return per;
}
}
7.万事具备,这个时候我们根据场景,比如某公司同时需要招JAVA以及前端工程师来做实现。在有了PersonnelBuilder 这个构造者之后,直接创建出来,构造他的招聘计划,提供给人事部门。人事直接把计划发布出去。优雅
public static void main(String[] args) {
//创建构造者
PersonnelBuilder builder = new PersonnelBuilder();
//开始构造
Personnel personnel = builder.builder();
personnel.push();
}
看看运行结果:
本公司开始招人了
Java工程师5个要求工作年限10年
Html5工程师1个要求工作年限10年
四.总结
1.优点
- 建造者模式将建造代码与表示代码分离,可以使客户端不需要知道产品的内部细节,从而降低了客户端与具体产品间的耦合度
- 每一个建造者都互不相关,处于独立,利于项目的扩展
2.缺点
- 对于使用范围有限制,产品类必须有共同点,如果产品之间的差异性很大,则不适合使用建造者模式
3.与工厂方法模式比较
- 都属于创建型模式
- 建造者模式由指挥者类或建造者来组装对象,利用不同的组装顺序,可以创建更加复杂的对象
- 工厂方法模式将对象的全部创建过程封装在工厂类中,不关注创建的顺序
4.使用场景
- 产品类(本例的Requirement)比较复杂,通过调用的顺序不同产生不同的结果适合使用建造者模式
- 一个对象的创建过程比较复杂,为了简化创建过程可以由一个封装类代替创建