建造器模式(builder)

2024-06-23 04:08
文章标签 builder 建造 模式

本文主要是介绍建造器模式(builder),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

  • 1帅气的 Builder 链式调用?

    • 1.1普通对象的创建

      • 1.1.1重叠构造器

      • 1.1.2javabeans模式

    • 1.2builder链式调用的好处
  • 2应用的场景
  • 3感悟

帅气的 Builder 链式调用?
1.1普通对象的创建
再说正题之前。先看一下
在日常开发中,经常可以看到这样的代码:

Retrofit retrofit = new Retrofit.Builder().baseUrl("https://api.github.com/").build();

以及

new AlertDialog.Builder(this).setTitle("hello").setMessage("张三").setIcon(R.drawable.bg_search_corner).setCancelable(true).setOnCancelListener(new DialogInterface.OnCancelListener() {@Overridepublic void onCancel(DialogInterface dialog) {//...}}).show();

看到这样链式调用看起来好整齐啊,这既是Builder 模式,今天就来详细了解一下。
镜头切回来,先问大家普通对象的创建 有几种?
常见的有两种方式:重叠构造器,javabeans模式

1.1.1重叠构造器

在我们开发中我们可能经常写这种代码

 Person person = new Person("jiangnan","25","school","sh");

这种方式创建对象在属性不是很多的时候没感觉有什么别扭,假如现在随着业务的扩大,属性增加到几十个, 那我们每次创建对象的时候是不是有头重脚轻的感觉呢

 Person person = new Person("jiangnan","25","school","sh","","","","","","","","","","","");
public class Person {private String name;private String age;private String school;private String adress;public Person(String name, String age, String school, String adress) {this.name = name;this.age = age;this.school = school;this.adress = adress;}
}
1.1.2javabeans模式

       遇到多种构造器参数的时候,我们还有第二个替代方法,即javaBeans模式,调用一个无参的构造器创建对象,然后调用setter()方法来设置每一个必要的参数,以及每一个可选的参数。

public class Person {private final String name;private String age;private String school;private String adress;public Person() {}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getAge() {return age;}public void setAge(String age) {this.age = age;}public String getSchool() {return school;}public void setSchool(String school) {this.school = school;}public String getAdress() {return adress;}public void setAdress(String adress) {this.adress = adress;}
}

这种方式弥补了上面重叠构造器模式的不足,创建对象也很容易,读起来也很简单

 Person person = new Person();person.setName("jiangnan");person.setAge("25");person.setSchool("school");person.setAdress("sh");

但javabeans模式还有缺点

1:不优雅,
2:拿到的不是完整的对象

1.2builder链式调用的好处

幸运的是我们第三者替代方法,既能保证重叠构造器模式的安全性,还能保证javabeans模式那么好的可读性,这就是builder模式,不直接创建对象,而是先利用所有必要的参数调用构造器,得到一个builder对象,然后我们调用builder的类似于sertter方法来设置每一个可选的参数,最后,我们用户可以调用无参的build方法生成一个不可变的对象,这个builder是他构造的类的静态成员类。

public class Person {private String name;private String age;private String school;private String adress;/*** 构造参数是它的内部静态类,为了对静态内部类的变量进行赋值操作* @param builder*/public Person(Builder builder) {name=builder.mName;age=builder.mAge;school=builder.mSchool;adress=builder.mAdress;}public static class Builder{private final String mName; //必选参数 final 类型需要在 构造器中初始化,不允许不初始化它的构造器存在private String mAge;private String mSchool;private String mAdress;public Builder(String name){mName=name;}public Builder setAge(String age) {mAge = age;return this;}public Builder setSchool(String school) {mSchool = school;return this;}public Builder setAdress(String adress) {mAdress = adress;return this;}public Person build(){return new Person(this);}}
2应用的场景

譬如我们弹出对话框就是用到了builder设计模式

new AlertDialog.Builder(this).setMessage("加载对话框").setTitle("");

看goodle工程师对AlertDialog的源码你会发现构造是这样的

public class AlertDialog extends Dialog implements DialogInterface {protected AlertDialog(Context context) {this(context, 0);}protected AlertDialog(Context context, boolean cancelable, OnCancelListener cancelListener) {this(context, 0);setCancelable(cancelable);setOnCancelListener(cancelListener);}public static class Builder {private final AlertController.AlertParams P;/*** Creates a builder for an alert dialog that uses the default alert* dialog theme.* <p>* The default alert dialog theme is defined by* {@link android.R.attr#alertDialogTheme} within the parent* {@code context}'s theme.** @param context the parent context*/public Builder(Context context) {this(context, resolveDialogTheme(context, 0));}public Builder setTitle(@StringRes int titleId) {P.mTitle = P.mContext.getText(titleId);return this;}/*** Set the title displayed in the {@link Dialog}.** @return This Builder object to allow for chaining of calls to set methods*/public Builder setTitle(CharSequence title) {P.mTitle = title;return this;}/*** Set the title using the custom view {@code customTitleView}.* <p>* The methods {@link #setTitle(int)} and {@link #setIcon(int)} should* be sufficient for most titles, but this is provided if the title* needs more customization. Using this will replace the title and icon* set via the other methods.* <p>* <strong>Note:</strong> To ensure consistent styling, the custom view* should be inflated or constructed using the alert dialog's themed* context obtained via {@link #getContext()}.** @param customTitleView the custom view to use as the title* @return this Builder object to allow for chaining of calls to set*         methods*/public Builder setCustomTitle(View customTitleView) {P.mCustomTitleView = customTitleView;return this;}/*** Set the message to display using the given resource id.** @return This Builder object to allow for chaining of calls to set methods*/public Builder setMessage(@StringRes int messageId) {P.mMessage = P.mContext.getText(messageId);return this;}/*** Set the message to display.** @return This Builder object to allow for chaining of calls to set methods*/public Builder setMessage(CharSequence message) {P.mMessage = message;return this;}/*** Set the resource id of the {@link Drawable} to be used in the title.* <p>* Takes precedence over values set using {@link #setIcon(Drawable)}.** @return This Builder object to allow for chaining of calls to set methods*/public Builder setIcon(@DrawableRes int iconId) {P.mIconId = iconId;return this;}/*** Set the {@link Drawable} to be used in the title.* <p>* <strong>Note:</strong> To ensure consistent styling, the drawable* should be inflated or constructed using the alert dialog's themed* context obtained via {@link #getContext()}.** @return this Builder object to allow for chaining of calls to set*         methods*/public Builder setIcon(Drawable icon) {P.mIcon = icon;return this;}}public AlertDialog create() {// Context has already been wrapped with the appropriate theme.final AlertDialog dialog = new AlertDialog(P.mContext, 0, false);P.apply(dialog.mAlert);dialog.setCancelable(P.mCancelable);if (P.mCancelable) {dialog.setCanceledOnTouchOutside(true);}dialog.setOnCancelListener(P.mOnCancelListener);dialog.setOnDismissListener(P.mOnDismissListener);if (P.mOnKeyListener != null) {dialog.setOnKeyListener(P.mOnKeyListener);}return dialog;}
}

这么长的代码如果我们自己写的话是不是疯了,庆幸有大牛帮我们开发出了插件,可以直接用
Android Studio 中使用插件自动生成 变种 Builder 模式代码
在Plugins中搜索Inner Builder
这里写图片描述

然后Generate
这里写图片描述

这里写图片描述

然后生成

public class User {private final String name;private String age;private String school;private String adress;private User(Builder builder) {name = builder.name;age = builder.age;school = builder.school;adress = builder.adress;}public static final class Builder {private final String name;private String age;private String school;private String adress;public Builder(String name) {this.name = name;}public Builder age(String val) {age = val;return this;}public Builder school(String val) {school = val;return this;}public Builder adress(String val) {adress = val;return this;}public User build() {return new User(this);}}
}

3感悟

       我们后辈在学习过程中切勿想当然觉得这些都很简单,都是先人在实际开发中遇到的坑,不断总结被整理成设计模式,学习的路还很长,沉淀自己,

这篇关于建造器模式(builder)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1086185

相关文章

如何开启和关闭3GB模式

https://jingyan.baidu.com/article/4d58d5414dfc2f9dd4e9c082.html

十四、观察者模式与访问者模式详解

21.观察者模式 21.1.课程目标 1、 掌握观察者模式和访问者模式的应用场景。 2、 掌握观察者模式在具体业务场景中的应用。 3、 了解访问者模式的双分派。 4、 观察者模式和访问者模式的优、缺点。 21.2.内容定位 1、 有 Swing开发经验的人群更容易理解观察者模式。 2、 访问者模式被称为最复杂的设计模式。 21.3.观察者模式 观 察 者 模 式 ( Obser

Builder模式的实现

概念 在创建复杂对象时,将创建该对象的工作交给一个建造者,这个建造者就是一个Builder。在日常的开发中,常常看到,如下这些代码: AlertDialog的实现 AlertDialog.Builder builder = new AlertDialog.Builder(context);builder.setMessage("你好建造者");builder.setTitle

[分布式网络通讯框架]----ZooKeeper下载以及Linux环境下安装与单机模式部署(附带每一步截图)

首先进入apache官网 点击中间的see all Projects->Project List菜单项进入页面 找到zookeeper,进入 在Zookeeper主页的顶部点击菜单Project->Releases,进入Zookeeper发布版本信息页面,如下图: 找到需要下载的版本 进行下载既可,这里我已经下载过3.4.10,所以以下使用3.4.10进行演示其他的步骤。

《分析模式》“鸦脚”表示法起源,Everest、Barker和Hay

DDD领域驱动设计批评文集 做强化自测题获得“软件方法建模师”称号 《软件方法》各章合集 《分析模式》这本书里面用的并不是UML表示法。作者Martin Fowler在书中也说了,该书写于1994-1995年,当时还没有UML。作者在书中用的是一种常被人称为“鸦脚”的表示法。  有的同学会有误解,例如有同学发表以下感想: “鸦脚”表示法当然不是Fowler先使用的。F

设计模式学习之中介者模式

我们平时写代码的过程,一个类必然会与其他类产生依赖关系,如果这种依赖关系如网状般错综复杂,那么必然会影响我们的代码逻辑以及执行效率,适当地使用中介者模式可以对这种依赖关系进行解耦使逻辑结构清晰,本篇博客,我们就一起学习中介者模式。 定义及使用场景 定义:中介者模式包装了一系列对象相互作用的方式,使得这些对象不必相互明显作用。从而使它们可以松散耦合。当某些对象之间的作用发生改变时,不会立即影响其

设计模式学习之模版方法模式

模板方法模式是一种基于继承的代码复用的行为型模式;在其结构中只存在父类与子类之间的继承关系。通过使用模板方法模式,可以将一些复杂流程的实现步骤封装在一系列基本方法中,在抽象父类中提供一个称之为模板方法的方法来定义这些基本方法的执行次序,而通过其子类来覆盖某些步骤,从而使得相同的算法框架可以有不同的执行结果。本篇博客我们一起来学习模版方法模式。 定义与UML图 定义 模板方法模式:定义一个操作

Android设计模式学习之Builder模式

Android设计模式学习之观察者模式 建造者模式(Builder Pattern),是创造性模式之一,Builder 模式的目的则是为了将对象的构建与展示分离。Builder 模式是一步一步创建一个复杂对象的创建型模式,它允许用户在不知道内部构建细节的情况下,可以更精细地控制对象的构造流程。 模式的使用场景 1.相同的方法,不同的执行顺序,产生不同的事件结果时; 2.多个部件或零件,都可

【设计模式-04】原型模式

【设计模式-04】原型模式 1. 概述2. 结构3. 实现4. 案例5. 使用场景6. 优缺点6.1 原型模式的优点6.2 原型模式的缺点 7. 实现深克隆(深拷贝) 1. 概述 原型模式: 用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型对象相同的新对象。 2. 结构 原型模式包含如下角色: 抽象原型类:规定了具体原型对象必须实现的 clone() 方法。