前言
在接下来的时间,每周都会给大家分享一个设计模式,欢迎大家关注、留言。
源码地址(欢迎star)
设计模式是什么?为什么要学习设计模式?
设计模式是程序员在设计应用程序或系统时可以用来解决常见问题的最佳做法。
设计模式可以通过提供经过验证的开发范例来加快开发过程。
重用设计模式有助于防止可能导致重大问题的微妙问题,并且还提高了熟悉模式的编码人员和架构师的代码可读性。
Builder模式的定义
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
Builder模式应用举例(Glide)
做安卓的小伙伴对Glide应该很清楚,在使用的过程中是不是都被它的设计所吸引?使用举例:
Glide.with(context).load(banner.getImageUrl()).into(imageView);
Builder模式的简单实现
- 欲创建的类
public final class Hero {
private final Profession profession;
private final String name;
private final HairType hairType;
private final HairColor hairColor;
private final Armor armor;
private final Weapon weapon;
private Hero(Builder builder) {
this.profession = builder.profession;
this.name = builder.name;
this.hairColor = builder.hairColor;
this.hairType = builder.hairType;
this.weapon = builder.weapon;
this.armor = builder.armor;
}
public Profession getProfession() {
return profession;
}
public String getName() {
return name;
}
public HairType getHairType() {
return hairType;
}
public HairColor getHairColor() {
return hairColor;
}
public Armor getArmor() {
return armor;
}
public Weapon getWeapon() {
return weapon;
}
}
- Builder静态内部类
public static class Builder {
private final Profession profession;
private final String name;
private HairType hairType;
private HairColor hairColor;
private Armor armor;
private Weapon weapon;
/**
* Constructor
*/
public Builder(Profession profession, String name) {
if (profession == null || name == null) {
throw new IllegalArgumentException("profession and name can not be null");
}
this.profession = profession;
this.name = name;
}
public Builder setHairType(HairType hairType) {
this.hairType = hairType;
return this;
}
public Builder setHairColor(HairColor hairColor) {
this.hairColor = hairColor;
return this;
}
public Builder setArmor(Armor armor) {
this.armor = armor;
return this;
}
public Builder setWeapon(Weapon weapon) {
this.weapon = weapon;
return this;
}
public Hero build() {
return new Hero(this);
}
}
- 注意点:Hero类构造方法私有;Builder类中的build方法实例化了Hero。所以想实例化Hero就可以通过以下方式
Hero hero = new Hero.Builder(Profession.WARRIOR, "Amberjill")
.setHairColor(HairColor.BLOND)
.setHairType(HairType.LONG_CURLY)
.setArmor(Armor.CHAIN_MAIL)
.setWeapon(Weapon.SWORD)
.build();
使用场景
- 当初始化一个对象特别复杂(参数多)时。
- 构建过程必须允许对所构造对象的不同表示。
- 创建复杂对象的算法应该独立于组成对象的部分以及它们是如何组装的。
Android源码中的Builder模式实现
在Android源码中,最常用的Builder模式就是AlertDialog.Builder, 使用该Builder来构建复杂的AlertDialog对象,具体示例如下:
AlertDialog dialog = new AlertDialog.Builder(appContext)
.setIcon(xxx)
.setMessage(xxx)
.setTitle(xxx)
.setNegativeButton(xxx)
.create(xxx)
dialog.show();
通过Builder对象来组装Dialog的各个部分,如title、button、message等,将Dialog的构造和表示进行分离。下面我看一下AlertDialog的相关源码:
public class AlertDialog extends AppCompatDialog implements DialogInterface {
protected AlertDialog(@NonNull Context context) {
this(context, 0);
}
protected AlertDialog(@NonNull Context context, @StyleRes int themeResId) {
super(context, resolveDialogTheme(context, themeResId));
mAlert = new AlertController(getContext(), this, getWindow());
}
protected AlertDialog(@NonNull Context context, boolean cancelable,
@Nullable OnCancelListener cancelListener) {
this(context, 0);
setCancelable(cancelable);
setOnCancelListener(cancelListener);
}
@Override
public void setTitle(CharSequence title) {
super.setTitle(title);
mAlert.setTitle(title);
}
public void setCustomTitle(View customTitleView) {
mAlert.setCustomTitle(customTitleView);
}
public void setMessage(CharSequence message) {
mAlert.setMessage(message);
}
public void setView(View view) {
mAlert.setView(view);
}
//省略其他代码
public static class Builder {
private final AlertController.AlertParams P;
private final int mTheme;
public Builder(@NonNull Context context) {
this(context, resolveDialogTheme(context, 0));
}
public Builder(@NonNull Context context, @StyleRes int themeResId) {
P = new AlertController.AlertParams(new ContextThemeWrapper(
context, resolveDialogTheme(context, themeResId)));
mTheme = themeResId;
}
@NonNull
public Context getContext() {
return P.mContext;
}
public Builder setTitle(@StringRes int titleId) {
P.mTitle = P.mContext.getText(titleId);
return this;
}
public Builder setTitle(@Nullable CharSequence title) {
P.mTitle = title;
return this;
}
public Builder setCustomTitle(@Nullable View customTitleView) {
P.mCustomTitleView = customTitleView;
return this;
}
public Builder setMessage(@StringRes int messageId) {
P.mMessage = P.mContext.getText(messageId);
return this;
}
public Builder setMessage(@Nullable CharSequence message) {
P.mMessage = message;
return this;
}
public Builder setIcon(@DrawableRes int iconId) {
P.mIconId = iconId;
return this;
}
public Builder setIcon(@Nullable Drawable icon) {
P.mIcon = icon;
return this;
}
public Builder setIconAttribute(@AttrRes int attrId) {
TypedValue out = new TypedValue();
P.mContext.getTheme().resolveAttribute(attrId, out, true);
P.mIconId = out.resourceId;
return this;
}
public Builder setPositiveButton(@StringRes int textId, final OnClickListener listener) {
P.mPositiveButtonText = P.mContext.getText(textId);
P.mPositiveButtonListener = listener;
return this;
}
public Builder setPositiveButton(CharSequence text, final OnClickListener listener) {
P.mPositiveButtonText = text;
P.mPositiveButtonListener = listener;
return this;
}
//省略其他代码
public AlertDialog create() {
final AlertDialog dialog = new AlertDialog(P.mContext, mTheme);
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;
}
}
总结
Builder模式在Android开发中较为常用,通常作为配置类的构建器将配置的构建和表示分离出来,同时也是讲配置从目标类中隔离出来,避免过多的setter方法。在今后的开发中可以尝试使用。
更多内容可以关注我的公众号或者搜索SamuelAndroid关注我: