GOF(二)-建造者模式(通过嵌套内部类的方式)【推荐】

建造者模式(Builder Pattern)

建造者:需要创建和提供实例,所以是创建型


用户只能看到稳定的接口,后面频繁变动的内容看不到。
所以优点就是:容易扩展,方便控制风险

由于建造者模式一般通过extends继承或implement实现接口完成。
所以缺点就是:需要有很多共同点,因此范围有限;易扩展容易出现很多的建造类
在这里插入图片描述

注意建造者模式比工厂模式更加关注组装顺序
工厂模式用于处理如何获取实例对象问题,建造者模式用于处理如何建造实例对象的问题

理论不再过多赘述,网上很多,这里就贴个图
建造者模式
UML的相关知识,可以访问我的另外一篇博文

注意: 图中是继承实现的,而我下面的代码是使用接口实现的,本质相同。

比较多的一种版本

代码如下:
创建具体的产品,比如别墅(住房中的一中)相当于这里的Product,可以理解为一个普通的entity类

public class House {

    private String roof; // 房顶

    private String wall; // 墙

    private String door; // 门

    public String getRoof() {
        return roof;
    }

    public void setRoof(String roof) {
        this.roof = roof;
    }

    public String getWall() {
        return wall;
    }

    public void setWall(String wall) {
        this.wall = wall;
    }

    public String getDoor() {
        return door;
    }

    public void setDoor(String door) {
        this.door = door;
    }

    @Override
    public String toString() {
        return "House{" +
                "roof='" + roof + '\'' +
                ", wall='" + wall + '\'' +
                ", door='" + door + '\'' +
                '}';
    }
}

接着创建IBuildHouse,相当于Builder接口

/**
 * @description:
 * 具体的产品
 */
public interface IBuildHouse {

    void buildRoof();

    void buildWall();

    void buildDoor();

    House createHouse(); // 返回具体的产品
}

接着创建别墅Praetorium,相当于ConcreteBuilder,用来实现接口

/**
 * @description:
 * 具体的建造者,实现接口
 */
public class BuildHouseImpl implements IBuildHouse{

    // 引用产品House
    private House house;

    public BuildHouseImpl() {
        house = new House();
    }

    @Override
    public void buildRoof() {
        house.setRoof("瓦片");
    }

    @Override
    public void buildWall() {
        house.setWall("土块");
    }

    @Override
    public void buildDoor() {
        house.setDoor("木头板");
    }

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

频繁变动的地方写完了,最后要写一个稳定的方法来调用频繁变动的方法。
这里使用Director找建筑队并监督建造别墅。

public class Director {
	// 这里传入接口
    public House createHouseByDirector(IBuildHouse buildHouse) {
        buildHouse.buildWall();
        buildHouse.buildDoor();
        buildHouse.buildRoof();
		// 返回一个House,不能造完连房子都不像
        return buildHouse.createHouse();
    }
}

测试代码:通过Director监督完成

    public static void main(String[] args) {
        Director director = new Director();
        // new一个具体的产品,这里是我的小别墅规划图
        House houseByDirector = 
        		director.createHouseByDirector(new Praetorium());

        System.out.println(houseByDirector);
    }

扩展方式: 多写几种房子类型继承IBuildHouse, 就可以实现扩展了。


通过嵌套内部类的方式实现建造者模式

创建entity类

public class Person {

    private Long id;

    private String name;

    private int age;

    private String address;

	// 注意:这里个无参构造方法最好为private
	// 这样才会通过PersonBuilder创建对象
    private Person(){}
    
	// 注意Person 只有get方法,没有set方法
	// 所有的赋值操作放在了PersonBuilder中
    public Long getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public String getAddress() {
        return address;
    }

    @Override
    public String toString() {
        return "Person{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                ", address='" + address + '\'' +
                '}';
    }

	// 嵌套内部类
    public static class PersonBuilder {

        Person person;

        // 若id,name是必填属性,可以这样编写
        // 当创建Person时,必须传入id,name
        public PersonBuilder(Long id, String name) {
           person = new Person();
           person.id = id;
           person.name = name;
        }

        // 若id,name 不是 必填属性,可以注释上面的PersonBuilder()
        // 并打开下方的所有注释代码
        /* public PersonBuilder() {
            person = new Person();
        }*/

        //  链式调用============================
        /* public PersonBuilder id(Long id){
            person.id = id;
            return this;
        }

        public PersonBuilder name(String name){
            person.name = name;
            return this;
        }*/

        public PersonBuilder age(int age) {
            person.age = age;
            return this;
        }

        public PersonBuilder address(String address) {
            person.address = address;
            return this;
        }
        //  ====================================

        // 返回 person,令Builder建造的结果可以用Person接收
        // 否则只能返回Person.PersonBuilder
        public Person build() {
            return person;
        }
    }
}

测试代码:

    public static void main(String[] args) {

        // id, name是必填属性
        Person person = new Person.PersonBuilder(12L, "lisi")
                .address("12345")
                .age(123)
                .build();

        // id, name 不是  必填属性
        // Person lisi = new Person.PersonBuilder()
        //         .address("12345")
        //         .age(123)
        //         .name("lisi")
        //         .build();

        System.out.println(person);
    }

非常重要:建造者模式到这就讲完了,如果有心,可以再看一下标题下的文字内容,结合UML图仔细再回味一下建造者模式,相信你可以理解的更深刻,记得更牢固。

代码已经上传到Git:请点击访问

如果大家对于建造者模式还有更多的使用技巧和使用心得,欢迎评论并在评论中分享自己的链接!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值