一、建造者模式的定义
Separate the construction of a complex object from its representation so that same construction process can create different representations(将一个复杂对象的构建与他的表示分离,使得同样的构建过程可以创建不同的表示)
二、建造者模式的应用
1、建造者模式的优点
封装性,使用建造者模式可以使客户端不必知道产品内部组成的细节。建造者独立,容易扩展 。便于控制细节风险由于具体的建造者是独立的,因此可以对建造过程逐步细化,而不对其他的模块产生任何影响。独立性,每个建造者相互独立,对系统的扩展非常有利。便于控制细节风险,由于具体的建造者是独立的,因此可以对建造过程逐步细化,而不对其他的模块产生任何的影响。
2、建造者模式的缺点
建造者模式创建的产品一般具有较多的共同点,其组成部分相似,如果产品之间的差异性很大,如组成部分很多不同,则不适合用建造者模式,因此,适用范围受到一定的限制如果产品内部变化复杂,可能会需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大,增加了系统的理解难度和运行成本
3、建造者模式使用场景
需要生成的产品对象的属性相互依赖,需要指定其生成顺序、需要生成的产品对象有复杂的内部结构,这些产品通常包含多个成员变量、对象的创建过程独立于创建该对象的类。在建造者模式中通过引入指挥者类,将创建过程封装在指挥者类中,而不在建造这类和客户类中、隔离复杂对象的创建和使用,并使得相同的创建过程创建不同的产品
三、建造者模式的写法
public abstract class Computer {
protected int mCpuCore = 1;
protected int mRamSize = 0;
protected String mOs = "Dos";
protected Computer() {
}
// 设置CPU核心数
public abstract void setCPU(int core);
// 设置内存
public abstract void setRAM(int gb);
// 设置操作系统
public abstract void setOs(String os);
@Override
public String toString() {
return "Computer [mCpuCore=" + mCpuCore + ", mRamSize=" + mRamSize
+ ", mOs=" + mOs + "]";
}
}
package com.dp.example.builder;
/**
* Apple电脑
*/
public class AppleComputer extends Computer {
protected AppleComputer() {
}
@Override
public void setCPU(int core) {
mCpuCore = core;
}
@Override
public void setRAM(int gb) {
mRamSize = gb;
}
@Override
public void setOs(String os) {
mOs = os;
}
}
/**
* builder抽象类
*
*/
public abstract class Builder {
// 设置CPU核心数
public abstract void buildCPU(int core);
// 设置内存
public abstract void buildRAM(int gb);
// 设置操作系统
public abstract void buildOs(String os);
// 创建Computer
public abstract Computer create();
}
package com.dp.example.builder;
public class ApplePCBuilder extends Builder {
private Computer mApplePc = new AppleComputer();
@Override
public void buildCPU(int core) {
mApplePc.setCPU(core);
}
@Override
public void buildRAM(int gb) {
mApplePc.setRAM(gb);
}
@Override
public void buildOs(String os) {
mApplePc.setOs(os);
}
@Override
public Computer create() {
return mApplePc;
}
}
public class Director {
Builder mBuilder = null;
/**
*
* @param builder
*/
public Director(Builder builder) {
mBuilder = builder;
}
/**
* 构建对象
*
* @param cpu
* @param ram
* @param os
*/
public void construct(int cpu, int ram, String os) {
mBuilder.buildCPU(cpu);
mBuilder.buildRAM(ram);
mBuilder.buildOs(os);
}
}
四、建造者模式源码中的应用
在Android代码中常见的就是AlterDialog.Builder
public class AlertDialog extends AppCompatDialog implements DialogInterface {
final AlertController mAlert;
static final int LAYOUT_HINT_NONE = 0;
static final int LAYOUT_HINT_SIDE = 1;
protected AlertDialog(@NonNull Context context) {
this(context, 0);
}
protected AlertDialog(@NonNull Context context, @StyleRes int themeResId) {
super(context, resolveDialogTheme(context, themeResId));
this.mAlert = new AlertController(this.getContext(), this, this.getWindow());
}
protected AlertDialog(@NonNull Context context, boolean cancelable, @Nullable OnCancelListener cancelListener) {
this(context, 0);
this.setCancelable(cancelable);
this.setOnCancelListener(cancelListener);
}
static int resolveDialogTheme(@NonNull Context context, @StyleRes int resid) {
if ((resid >>> 24 & 255) >= 1) {
return resid;
} else {
TypedValue outValue = new TypedValue();
context.getTheme().resolveAttribute(attr.alertDialogTheme, outValue, true);
return outValue.resourceId;
}
}
public Button getButton(int whichButton) {
return this.mAlert.getButton(whichButton);
}
public ListView getListView() {
return this.mAlert.getListView();
}
public void setTitle(CharSequence title) {
super.setTitle(title);
this.mAlert.setTitle(title);
}
public void setCustomTitle(View customTitleView) {
this.mAlert.setCustomTitle(customTitleView);
}
public void setMessage(CharSequence message) {
this.mAlert.setMessage(message);
}
public void setView(View view) {
this.mAlert.setView(view);
}
public void setView(View view, int viewSpacingLeft, int viewSpacingTop, int viewSpacingRight, int viewSpacingBottom) {
this.mAlert.setView(view, viewSpacingLeft, viewSpacingTop, viewSpacingRight, viewSpacingBottom);
}
@RestrictTo({Scope.LIBRARY_GROUP})
void setButtonPanelLayoutHint(int layoutHint) {
this.mAlert.setButtonPanelLayoutHint(layoutHint);
}
public void setButton(int whichButton, CharSequence text, Message msg) {
this.mAlert.setButton(whichButton, text, (OnClickListener)null, msg, (Drawable)null);
}
public void setButton(int whichButton, CharSequence text, OnClickListener listener) {
this.mAlert.setButton(whichButton, text, listener, (Message)null, (Drawable)null);
}
public void setButton(int whichButton, CharSequence text, Drawable icon, OnClickListener listener) {
this.mAlert.setButton(whichButton, text, listener, (Message)null, icon);
}
public void setIcon(int resId) {
this.mAlert.setIcon(resId);
}
public void setIcon(Drawable icon) {
this.mAlert.setIcon(icon);
}
public void setIconAttribute(int attrId) {
TypedValue out = new TypedValue();
this.getContext().getTheme().resolveAttribute(attrId, out, true);
this.mAlert.setIcon(out.resourceId);
}
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.mAlert.installContent();
}
public boolean onKeyDown(int keyCode, KeyEvent event) {
return this.mAlert.onKeyDown(keyCode, event) ? true : super.onKeyDown(keyCode, event);
}
public boolean onKeyUp(int keyCode, KeyEvent event) {
return this.mAlert.onKeyUp(keyCode, event) ? true : super.onKeyUp(keyCode, event);
}
public static class Builder {
private final AlertParams P;
private final int mTheme;
public Builder(@NonNull Context context) {
this(context, AlertDialog.resolveDialogTheme(context, 0));
}
public Builder(@NonNull Context context, @StyleRes int themeResId) {
this.P = new AlertParams(new ContextThemeWrapper(context, AlertDialog.resolveDialogTheme(context, themeResId)));
this.mTheme = themeResId;
}
@NonNull
public Context getContext() {
return this.P.mContext;
}
public AlertDialog.Builder setTitle(@StringRes int titleId) {
this.P.mTitle = this.P.mContext.getText(titleId);
return this;
}
public AlertDialog.Builder setTitle(@Nullable CharSequence title) {
this.P.mTitle = title;
return this;
}
public AlertDialog.Builder setCustomTitle(@Nullable View customTitleView) {
this.P.mCustomTitleView = customTitleView;
return this;
}
public AlertDialog.Builder setMessage(@StringRes int messageId) {
this.P.mMessage = this.P.mContext.getText(messageId);
return this;
}
public AlertDialog.Builder setMessage(@Nullable CharSequence message) {
this.P.mMessage = message;
return this;
}
public AlertDialog.Builder setIcon(@DrawableRes int iconId) {
this.P.mIconId = iconId;
return this;
}
public AlertDialog.Builder setIcon(@Nullable Drawable icon) {
this.P.mIcon = icon;
return this;
}
public AlertDialog.Builder setIconAttribute(@AttrRes int attrId) {
TypedValue out = new TypedValue();
this.P.mContext.getTheme().resolveAttribute(attrId, out, true);
this.P.mIconId = out.resourceId;
return this;
}
public AlertDialog.Builder setPositiveButton(@StringRes int textId, OnClickListener listener) {
this.P.mPositiveButtonText = this.P.mContext.getText(textId);
this.P.mPositiveButtonListener = listener;
return this;
}
public AlertDialog.Builder setPositiveButton(CharSequence text, OnClickListener listener) {
this.P.mPositiveButtonText = text;
this.P.mPositiveButtonListener = listener;
return this;
}
public AlertDialog.Builder setPositiveButtonIcon(Drawable icon) {
this.P.mPositiveButtonIcon = icon;
return this;
}
public AlertDialog.Builder setNegativeButton(@StringRes int textId, OnClickListener listener) {
this.P.mNegativeButtonText = this.P.mContext.getText(textId);
this.P.mNegativeButtonListener = listener;
return this;
}
public AlertDialog.Builder setNegativeButton(CharSequence text, OnClickListener listener) {
this.P.mNegativeButtonText = text;
this.P.mNegativeButtonListener = listener;
return this;
}
public AlertDialog.Builder setNegativeButtonIcon(Drawable icon) {
this.P.mNegativeButtonIcon = icon;
return this;
}
public AlertDialog.Builder setNeutralButton(@StringRes int textId, OnClickListener listener) {
this.P.mNeutralButtonText = this.P.mContext.getText(textId);
this.P.mNeutralButtonListener = listener;
return this;
}
public AlertDialog.Builder setNeutralButton(CharSequence text, OnClickListener listener) {
this.P.mNeutralButtonText = text;
this.P.mNeutralButtonListener = listener;
return this;
}
public AlertDialog.Builder setNeutralButtonIcon(Drawable icon) {
this.P.mNeutralButtonIcon = icon;
return this;
}
public AlertDialog.Builder setCancelable(boolean cancelable) {
this.P.mCancelable = cancelable;
return this;
}
public AlertDialog.Builder setOnCancelListener(OnCancelListener onCancelListener) {
this.P.mOnCancelListener = onCancelListener;
return this;
}
public AlertDialog.Builder setOnDismissListener(OnDismissListener onDismissListener) {
this.P.mOnDismissListener = onDismissListener;
return this;
}
public AlertDialog.Builder setOnKeyListener(OnKeyListener onKeyListener) {
this.P.mOnKeyListener = onKeyListener;
return this;
}
public AlertDialog.Builder setItems(@ArrayRes int itemsId, OnClickListener listener) {
this.P.mItems = this.P.mContext.getResources().getTextArray(itemsId);
this.P.mOnClickListener = listener;
return this;
}
public AlertDialog.Builder setItems(CharSequence[] items, OnClickListener listener) {
this.P.mItems = items;
this.P.mOnClickListener = listener;
return this;
}
public AlertDialog.Builder setAdapter(ListAdapter adapter, OnClickListener listener) {
this.P.mAdapter = adapter;
this.P.mOnClickListener = listener;
return this;
}
public AlertDialog.Builder setCursor(Cursor cursor, OnClickListener listener, String labelColumn) {
this.P.mCursor = cursor;
this.P.mLabelColumn = labelColumn;
this.P.mOnClickListener = listener;
return this;
}
public AlertDialog.Builder setMultiChoiceItems(@ArrayRes int itemsId, boolean[] checkedItems, OnMultiChoiceClickListener listener) {
this.P.mItems = this.P.mContext.getResources().getTextArray(itemsId);
this.P.mOnCheckboxClickListener = listener;
this.P.mCheckedItems = checkedItems;
this.P.mIsMultiChoice = true;
return this;
}
public AlertDialog.Builder setMultiChoiceItems(CharSequence[] items, boolean[] checkedItems, OnMultiChoiceClickListener listener) {
this.P.mItems = items;
this.P.mOnCheckboxClickListener = listener;
this.P.mCheckedItems = checkedItems;
this.P.mIsMultiChoice = true;
return this;
}
public AlertDialog.Builder setMultiChoiceItems(Cursor cursor, String isCheckedColumn, String labelColumn, OnMultiChoiceClickListener listener) {
this.P.mCursor = cursor;
this.P.mOnCheckboxClickListener = listener;
this.P.mIsCheckedColumn = isCheckedColumn;
this.P.mLabelColumn = labelColumn;
this.P.mIsMultiChoice = true;
return this;
}
public AlertDialog.Builder setSingleChoiceItems(@ArrayRes int itemsId, int checkedItem, OnClickListener listener) {
this.P.mItems = this.P.mContext.getResources().getTextArray(itemsId);
this.P.mOnClickListener = listener;
this.P.mCheckedItem = checkedItem;
this.P.mIsSingleChoice = true;
return this;
}
public AlertDialog.Builder setSingleChoiceItems(Cursor cursor, int checkedItem, String labelColumn, OnClickListener listener) {
this.P.mCursor = cursor;
this.P.mOnClickListener = listener;
this.P.mCheckedItem = checkedItem;
this.P.mLabelColumn = labelColumn;
this.P.mIsSingleChoice = true;
return this;
}
public AlertDialog.Builder setSingleChoiceItems(CharSequence[] items, int checkedItem, OnClickListener listener) {
this.P.mItems = items;
this.P.mOnClickListener = listener;
this.P.mCheckedItem = checkedItem;
this.P.mIsSingleChoice = true;
return this;
}
public AlertDialog.Builder setSingleChoiceItems(ListAdapter adapter, int checkedItem, OnClickListener listener) {
this.P.mAdapter = adapter;
this.P.mOnClickListener = listener;
this.P.mCheckedItem = checkedItem;
this.P.mIsSingleChoice = true;
return this;
}
public AlertDialog.Builder setOnItemSelectedListener(OnItemSelectedListener listener) {
this.P.mOnItemSelectedListener = listener;
return this;
}
public AlertDialog.Builder setView(int layoutResId) {
this.P.mView = null;
this.P.mViewLayoutResId = layoutResId;
this.P.mViewSpacingSpecified = false;
return this;
}
public AlertDialog.Builder setView(View view) {
this.P.mView = view;
this.P.mViewLayoutResId = 0;
this.P.mViewSpacingSpecified = false;
return this;
}
/** @deprecated */
@Deprecated
@RestrictTo({Scope.LIBRARY_GROUP})
public AlertDialog.Builder setView(View view, int viewSpacingLeft, int viewSpacingTop, int viewSpacingRight, int viewSpacingBottom) {
this.P.mView = view;
this.P.mViewLayoutResId = 0;
this.P.mViewSpacingSpecified = true;
this.P.mViewSpacingLeft = viewSpacingLeft;
this.P.mViewSpacingTop = viewSpacingTop;
this.P.mViewSpacingRight = viewSpacingRight;
this.P.mViewSpacingBottom = viewSpacingBottom;
return this;
}
/** @deprecated */
@Deprecated
public AlertDialog.Builder setInverseBackgroundForced(boolean useInverseBackground) {
this.P.mForceInverseBackground = useInverseBackground;
return this;
}
@RestrictTo({Scope.LIBRARY_GROUP})
public AlertDialog.Builder setRecycleOnMeasureEnabled(boolean enabled) {
this.P.mRecycleOnMeasure = enabled;
return this;
}
public AlertDialog create() {
AlertDialog dialog = new AlertDialog(this.P.mContext, this.mTheme);
this.P.apply(dialog.mAlert);
dialog.setCancelable(this.P.mCancelable);
if (this.P.mCancelable) {
dialog.setCanceledOnTouchOutside(true);
}
dialog.setOnCancelListener(this.P.mOnCancelListener);
dialog.setOnDismissListener(this.P.mOnDismissListener);
if (this.P.mOnKeyListener != null) {
dialog.setOnKeyListener(this.P.mOnKeyListener);
}
return dialog;
}
public AlertDialog show() {
AlertDialog dialog = this.create();
dialog.show();
return dialog;
}
}
}