那些你要知道的设计模式之-建造者

那些你要知道的设计模式之-建造者_第1张图片

一.定义

  1. 将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。

二.作用

  • 使类独立,易扩展,容易控制。
  • 使类的创建过程更加清晰,简单。

三.案例

故事背景:某上市公司的达摩院,需要招技术工程师,那么需要招那些技术呢?是Java还是Html5呢?
不同情况可能还不一样前期可能先招个Java过来把后台搞一搞,数据库表结构设计设计。等到后台搭建的差不多了,那就再招一个前端把数据展示展示,再过段随着业务的扩大,目前的人员配置不够了,需要扩招Java,Html人才都需要。也有的公司项目比较急,一开始就会把人员配齐,或者招一部分的都有。说了这么多其实想说的就是,不同公司招人的顺序不一样。这也是建造者模式中很重要的一点,顺序不同结果也不同

3.1实现

以公司招技术人员来例,也不是什么人都需要,对技术人员是有要求的,是要有经验的,过来就能干活,技术类型可以分为Java和Html5,Java的可以作为服务端(Server)他们是Java工程师,Html5的可以作为前端(Web)他们是前端工程师

然后对招聘要求(Requirement),针对不同岗位做不同实现,工作类型抽象成Job接口,由人事部门负责收集不同的招聘要求(List)发布招聘信息,PersonnelBuilder根据不同的招聘需求构建不同的Personnel人事实现不同的招聘计划。设计图如下:


那些你要知道的设计模式之-建造者_第2张图片
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)比较复杂,通过调用的顺序不同产生不同的结果适合使用建造者模式
  • 一个对象的创建过程比较复杂,为了简化创建过程可以由一个封装类代替创建

你可能感兴趣的:(那些你要知道的设计模式之-建造者)