建造者模式

建造模式

介绍

该子标题中内容,来源菜鸟教程

意图

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

主要解决

主要解决在软件系统中,有时候面临着"一个复杂对象"的创建工作,其通常由各个部分的子对象用一定的算法构成;由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法却相对稳定。

何时使用

一些基本部件不会变,而其组合经常变化的时候。

如何解决

将变与不变分离开。

优点

  1. 建造者独立,易扩展。
  2. 便于控制细节风险。

缺点:

  1. 产品必须有共同点,范围有限制。
  2. 如内部变化复杂,会有很多的建造类。

使用场景

  1. 需要生成的对象具有复杂的内部结构。
  2. 需要生成的对象内部属性本身相互依赖。

注意事项

与工厂模式的区别是:建造者模式更加关注与零件装配的顺序。

代码

模式角色和职责

产品对象

复杂的内部属性集合的bean。
本文的例子:Company和CompanyPersonnel对象

抽象构建类

主要用来对产品的属性进行构建
本文的例子:CompanyBuilder对象

具体的构建类

该类实现 【抽象构建类】 ,对产品中的属性进行具体的创建
本文的例子:ATestCompanyBuilder对象

导演类

对产品进行具体的组装。
【具体的构建类】指的是产品中的属性进行构建,
而该类是获取最终的产品对象
本文的例子:Director对象

场景

代码含义

没有复杂业务,简单代码展示,对一个公司和员工的 bean 进行构建。

代码展示

产品对象

公司对象

package com.builderpattern.vo;

import lombok.Data;

import java.util.List;

/**
 * @version v1.0
 * @Copyright(c): 2020-2020
 * @FileName: Company.java
 * @Description: 公司对象
 * @autho Admin
 * @date 2020/1/13 11:35
 */
@Data
public class Company {

    /**
     * 名称
     */
    private String name;

    /**
     * 公司统一社会信用代码(公司的唯一标识)
     */
    private String socialId;

    /**
     * 企业员工
     */
    private List<CompanyPersonnel> companyPersonnelList;
}

公司员工对象

package com.builderpattern.vo;

import lombok.Data;

/**
 * @version v1.0
 * @Copyright(c): 2020-2020
 * @FileName: CompanyPersonnel.java
 * @Description:
 * @autho Admin
 * @date 2020/1/13 13:54
 */
@Data
public class CompanyPersonnel {

    /**
     * 员工姓名
     */
    private String name;

    /**
     * 员工编号
     */
    private String number;

    /**
     * 员工年龄
     */
    private Integer age;

    /**
     * 员工性别  0:男  1:女
     */
    private String sex;
}
抽象构建类
package com.builderpattern.build;

import com.builderpattern.vo.Company;
import com.builderpattern.vo.CompanyPersonnel;

import java.util.List;

/**
 * @version v1.0
 * @Copyright(c): 2020-2020
 * @FileName: CompanyBuilder.java
 * @Description:
 * @autho Admin
 * @date 2020/1/13 13:56
 */
public abstract class CompanyBuilder {
    //创建公司对象(产品)
    protected Company company = new Company();

    /**
     * 产品属性建造  公司名称 可以通过外部传入获取
     * @return
     */
    public abstract CompanyBuilder buildName(String name);

    /**
     * 产品属性建造  统一社会信用代码
     * @return
     */
    public abstract CompanyBuilder buildSocialId();

    /**
     * 产品属性建造  公司员工集合
     * @return
     */
    public abstract CompanyBuilder buildPersonnelList();

    /**
     * 提供一个方法,可以得到产品
     * @return
     */
    public Company getCompany(){
        return company;
    }
}
具体的构建类
package com.builderpattern.build;

import com.builderpattern.vo.CompanyPersonnel;
import org.apache.commons.lang3.RandomUtils;

import java.util.ArrayList;
import java.util.List;

/**
 * @version v1.0
 * @Copyright(c): 2020-2020
 * @FileName: ATestCompanyBuilder.java
 * @Description: A测试公司建造
 * @autho Admin
 * @date 2020/1/13 14:04
 */
public class ATestCompanyBuilder extends CompanyBuilder{

    public CompanyBuilder buildName(String name) {
        company.setName(name);
        return this;
    }

    public CompanyBuilder buildSocialId() {
        company.setSocialId("91123123213213211A");
        return this;
    }

    public CompanyBuilder buildPersonnelList() {
        ArrayList<CompanyPersonnel> list = new ArrayList<CompanyPersonnel>();
        for (int i = 0; i < 10; i++) {
            CompanyPersonnel companyPersonnel = new CompanyPersonnel();
            companyPersonnel.setAge(18+i);
            companyPersonnel.setName("测试员工"+(i+1));
            companyPersonnel.setNumber(String.valueOf(i+1));
            companyPersonnel.setSex(i%2==0?"0":"1");
            list.add(companyPersonnel);
        }
        company.setCompanyPersonnelList(list);
        return this;
    }

}
导演类
package com.builderpattern.director;

import com.builderpattern.build.CompanyBuilder;
import com.builderpattern.vo.Company;
import lombok.Data;

/**
 * @version v1.0
 * @Copyright(c): 2020-2020
 * @FileName: Director.java
 * @Description:
 * @autho Admin
 * @date 2020/1/13 14:19
 */
@Data
public class Director {
    //获取build的基类对象,可以通过有参构造传入
    private CompanyBuilder companyBuilder;

    public Director(CompanyBuilder companyBuilder){
        this.companyBuilder = companyBuilder;
    }

    //负责公司(产品)对象的创建
    public Company construct(String name){
        return companyBuilder.buildName(name)
                .buildPersonnelList()
                .buildSocialId()
                .getCompany();
    }
}
测试类
package com.builderpattern;

import com.builderpattern.build.ATestCompanyBuilder;
import com.builderpattern.build.CompanyBuilder;
import com.builderpattern.director.Director;
import com.builderpattern.vo.Company;

/**
 * @version v1.0
 * @Copyright(c): 2020-2020
 * @FileName: Test.java
 * @Description:
 * @autho Admin
 * @date 2020/1/13 14:23
 */
public class Test {
    public static void main(String[] args) {
        //创建建造者
        CompanyBuilder builder = new ATestCompanyBuilder();
        //通过Director统一组建,并获取产品
        Director director = new Director(builder);
        Company construct = director.construct("A测试公司");

        System.out.println(construct);
    }
}
测试结果
Company(name=A测试公司, socialId=91123123213213211A,
companyPersonnelList=
[CompanyPersonnel(name=测试员工1, number=1, age=18, sex=0),
CompanyPersonnel(name=测试员工2, number=2, age=19, sex=1),
CompanyPersonnel(name=测试员工3, number=3, age=20, sex=0),
CompanyPersonnel(name=测试员工4, number=4, age=21, sex=1),
CompanyPersonnel(name=测试员工5, number=5, age=22, sex=0),
CompanyPersonnel(name=测试员工6, number=6, age=23, sex=1),
CompanyPersonnel(name=测试员工7, number=7, age=24, sex=0),
CompanyPersonnel(name=测试员工8, number=8, age=25, sex=1),
CompanyPersonnel(name=测试员工9, number=9, age=26, sex=0),
CompanyPersonnel(name=测试员工10, number=10, age=27, sex=1)])

什么时候使用

本文产品中的成员变量比较少,如果在业务比较复杂,成员变量很多,需要的有参构造方法比较多(而且可能有的成员变量要使用,有的不要使用,很容易乱。使用 set 多了,也会乱),难以维护,就可以使用该模式

附:目录结构

有需要源码的,也可以扫描下方二维码,加我好友,私聊我

- END -

本文分享自微信公众号 - JAVA知识总结与分享(summing_up_sharing),作者:爱笑的阿杰

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-01-13

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • springBoot学习(三)springBoot事件监听和部分注解的运用

    1.springBoot启动类会使用@SpringBootApplication 2.点进入源代码发现改注解是一个复合注解,由好几个注解共同组合而成

    杨小杰
  • 抽象工厂模式

    老板:阿飞,上次面包店老板找我聊了一下,他们是大规模的从各大小原料商铺进的原料,出现了好多偷工减料的情况,现在他们做大了,想自己开几个原料提供点,如果中国的顾客...

    杨小杰
  • 装饰者模式

    动态地将责任附加到对象上,若要拓展功能,装饰者提供了比继承更有弹性的替代方案对于设计模式。

    杨小杰
  • 继承

    虚继承是为了解决棱形继承中成员访问的二义性。在A B继承方式前加关键字virtual,编译器将Base的数据保存在一个公共位置,通过虚基表访问。

    DeROy
  • SpringBoot系列教程之Bean之指定初始化顺序的若干姿势

    上一篇博文介绍了@Order注解的常见错误理解,它并不能指定 bean 的加载顺序,那么问题来了,如果我需要指定 bean 的加载顺序,那应该怎么办呢?

    一灰灰blog
  • struts2: config-browser-plugin 与 convention-plugin 学习

    struts2被很多新手诟病的一个地方在于“配置过于复杂”,相信不少初学者因为这个直接改投Spring-MVC了。convention-plugin、 conf...

    菩提树下的杨过
  • VUE路由去除#问题

    最近自己在写一个vue的小型管理系统,在浏览器中看到的路由都是带有#的,很是不好看。为了解决此问题,大家一般都会想到:mode: 'history'。可是在开发...

    用户1174387
  • 控制反转-Ioc之Unity

    本篇幅主要介绍控制反转的一些概念,和如何使用Unity实现Ioc。在介绍的时候,会尽量结合代码来讲解一些概念。

    少羽大怪兽
  • Mybatis入门

    发现一个非常好的Mybatis详细教程,地址:https://www.w3cschool.cn/mybatis/

    SuperHeroes
  • MySQL INSERT INTO...ON DUPLICATE KEY UPDATE的使用

    1. 语法规则为: INSERT [INTO] tbl_name [(col_name,...)] {VALUES} ({expr | DEF...

    囚兔

扫码关注云+社区

领取腾讯云代金券