Java设计模式——构建器模式【Builder Pattern】(一)

一、引言

在日常的开发中,我们可能经常能看到如下的代码:

PrivateKeyDecryptParam param = new PrivateKeyDecryptParam.Builder()
                                              .uAppId(uAppId)
                                              .containerId(containerId)
                                              .cipher(cipher)
                                              .signFlag(signFlag)
                                              .build();

在Android中,也会看到下面创建AlertDialog代码:

new AlertDialog.Builder(this)
           .setTitle("标题")
           .setMessage("内容")
           .setCancelable(true)
           .setOnCancelListener(new DialogInterface.OnCancelListener() {
               @Override
               public void onCancel(DialogInterface dialog) {
                
               }
           })
           .show();

观察上面这两段代码,都有一个共同的特点,就是都可以进行链式操作,这就是我们要学习的Builder模式,下面就来详细学习一下。

二、Builder模式的使用场景

在《Effective Java第2版》书中有提到,当遇到多个构造器参数时,要考虑使用构建器(Builder模式)

举个例子,比如在项目中,我们需要新建一个Person类,假设该类有7个属性(现实中远不止这几个参数),其中有2个是必要的参数需要初始化,分别是id和name。

1. 使用JavaBean的setter方法来设置对象属性

最常见的写法应该是写成JavaBean。代码如下:

public class Person {
    //必要参数
    private int id;
    private String name;
    //可选参数
    private int age;
    private String sex;
    private String phone;
    private String address;
    private String desc;

  // set/get方法忽略
}

在使用该Person类的时候,会写出如下的代码:

Person person = new Person();
person.setId(1);
person.setName("张小毛");
person.setAge(22);
person.setSex("男");
person.setPhone("19999999999");
person.setAddress("beijing");
person.setDesc("JavaBeans模式");

这种JavaBean方式也是常见的构造对象并赋值的方式,这种方式的好处是:

  • 易于阅读,并且可以只对有用的成员变量赋值

但它的缺点是:

  • 成员变量不可以是 final 类型,失去了不可变对象的很多好处
  • 对象状态不连续,你必须调用7次setter方法才能得到一个具备7个属性值得变量,在这期间用户可能拿到不完整状态的对象。如果有N个属性,岂不是要person.setXXX调用N次?此种方式不优雅

最重要的缺点是第二条:对象状态不连续。 什么意思呢?

解释一下:这种方式是先创建对象、后赋值,用户不知道什么时候拿到的对象是完整的,构建完成的。很有可能你只setter了一两个属性就返回了,一些必要的属性没有被赋值。

2. 使用重叠构造器

在这种模式下,需要提供一个只有必要参数的构造器,第二个构造器有一个可选参数,第三个有两个可选参数,依此类推,最后一个构造器包含所有的可选参数。代码如下:

public class Person {
    //必要参数
    private final int id;
    private final String name;
    //可选参数
    private int age;
    private String sex;
    private String phone;
    private String address;
    private String desc;

    public Person(int id, String name) {
        this(id, name, 0);
    }

    public Person(int id, String name, int age) {
        this(id, name, age, "");
    }

    public Person(int id, String name, int age, String sex) {
        this(id, name, age, sex, "");
    }

    public Person(int id, String name, int age, String sex, String phone) {
        this(id, name, age, sex, phone, "");
    }

    public Person(int id, String name, int age, String sex, String phone,
                  String address) {
        this(id, name, age, sex, phone, address, "");
    }

    public Person(int id, String name, int age, String sex, String phone, 
                  String address, String desc) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.sex = sex;
        this.phone = phone;
        this.address = address;
        this.desc = desc;
    }
}

从上面的代码可以看出,当你想要创建实例的时候,就利用参数列表最短的构造器,但该列表中包含了要设置的所有参数,其余都为默认值:

Person person = new Persion(1, "张小毛");

这个构造器调用,通常需要许多你本不想设置的参数,但还是不得不为它们传递值。

这种方式的优点就是:简单!!!!(这是对开发者而言),但使用者在使用时,可得仔细了解你每个构造函数,否则一不小心填错顺序也不知道。而且如果有十几个属性,就歇菜了……(我也没见过有十几个参数的构造函数)

所以缺点是:只适用于成员变量少的情况,太多了不容易理解、维护。

简而言之:重叠构造器可行,但是当有许多参数的时候,创建使用代码会很难写,并且较难以阅读。

三、变种Builder模式

对于上述分析的两种方法,都存在优点和缺点,为了解决上述两种构建方式的不足,伟大的程序员们创造出了变种 Builder模式。直接看代码:

public class Person {
    //必要参数
    private final int id;
    private final String name;
    //可选参数
    private int age;
    private String sex;
    private String phone;
    private String address;
    private String desc;

    private Person(Builder builder) {
        this.id = builder.id;
        this.name = builder.name;
        this.age = builder.age;
        this.sex = builder.sex;
        this.phone = builder.phone;
        this.address = builder.address;
        this.desc = builder.desc;
    }

    public static class Builder {
        //必要参数
        private final int id;
        private final String name;
        //可选参数
        private int age;
        private String sex;
        private String phone;
        private String address;
        private String desc;

        public Builder(int id, String name) {
            this.id = id;
            this.name = name;
        }

        public Builder age(int val) {
            this.age = val;
            return this;
        }

        public Builder sex(String val) {
            this.sex = val;
            return this;
        }

        public Builder phone(String val) {
            this.phone = val;
            return this;
        }

        public Builder address(String val) {
            this.address = val;
            return this;
        }

        public Builder desc(String val) {
            this.desc = val;
            return this;
        }

        public Person build() {
            return new Person(this);
        }
    }
}

观察上述代码,可以看到变种Builder模式包括以下内容:

(1)、在要构建类的内部,创建一个静态内部类Builder;

(2)、静态内部类的属性要与构建类的属性一致;

(3)、构建类的构造参数是静态内部类,使用静态内部类的变量为构建类逐一赋值;

(4)、静态内部类提供参数的setter方法,并且返回值是当前Builder对象;

(5)、最终提供一个build方法new出来一个构建类的对象,参数是当前Builder对象;

调用代码如下:

	public class Test {
	
	    public static void main(String[] args) {
	        Person person = new Person.Builder(1, "张小毛")
	                .age(22).sex("男").desc("使用builder模式").build();
	        System.out.println(person.toString());
	    }
	}

对变种Builer模式的总结:

  • 变种Builder模式目的在于:减少对象创建过程中引入的多个构造函数、可选参数以及多个setter过度使用导致的不必要的复杂性。

  • 优点就是:看起来很整齐;先赋值,后创建对象,最终调用build()方法才创建了构建类的对象,保证了状态的完整性。

  • 缺点嘛,就是需要额外写的代码多了点。

四、小结:

变种Builer模式相比于重叠构造器模式和JavaBean模式,Builder模式实现的对象更利于使用。

对Builer模式使用方法的总结:

  • 外部类的构造函数私有,且参数为静态内部类;
  • 静态内部类拥有外部类相同的属;
  • 为每一个属性,写一个方法,返回的是Builer;
  • 最后一个方法是build方法,用于构建一个外部类;
  • 40
    点赞
  • 86
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 8
    评论
非常抱歉,我误解了你的问题。你的第一句话是"java设计模式"。那么,接下来我将为你介绍一些常见的 Java 设计模式Java 设计模式是一套被广泛应用于面向对象软件设计的可重用解决方案。它们提供了一种在软件开发过程中常见问题的解决方案,并帮助开发人员写出易于理解、可维护和可扩展的代码。 以下是一些常见的 Java 设计模式: 1. 创建型模式(Creational Patterns):包括工厂模式(Factory Pattern)、抽象工厂模式(Abstract Factory Pattern)、单例模式(Singleton Pattern)、建造者模式Builder Pattern)和原型模式(Prototype Pattern)等。 2. 结构型模式(Structural Patterns):包括适配模式(Adapter Pattern)、桥接模式(Bridge Pattern)、装饰模式(Decorator Pattern)、组合模式(Composite Pattern)、外观模式(Facade Pattern)、享元模式(Flyweight Pattern)和代理模式(Proxy Pattern)等。 3. 行为型模式(Behavioral Patterns):包括策略模式(Strategy Pattern)、模板方法模式(Template Method Pattern)、观察者模式(Observer Pattern)、迭代模式(Iterator Pattern)、责任链模式(Chain of Responsibility Pattern)、命令模式(Command Pattern)、备忘录模式(Memento Pattern)、状态模式(State Pattern)、访问者模式(Visitor Pattern)和中介者模式(Mediator Pattern)等。 这些设计模式都有各自的特点和应用场景,可以根据实际需求选择合适的模式来优化和改进你的 Java 代码。希望这些信息对你有所帮助!如有更多问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

止步前行

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值