建造者模式

建造者模式(Builder Pattern)使用多个简单的对象一步一步构建成一个复杂的对象。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

建造者模式的优点: 1.使用起来简单,让人感觉很好。 2.屏蔽了组件的内部细节,将组件本身和创建过程进行解耦分离,同一个 Builder 设置不同的参数,即可创建适应不同需求的组件。3.扩展容易,通过设置Builder的参数即可完成不同需求的定制。

缺点: 不适用于需求或者差异化比较大的组件。

下面看一段Android的代码

new AlertDialog.Builder(this)
            .setTitle("title")
            .setMessage("message")
            .setIcon(R.mipmap.ic_launcher)
            .create()
            .show();

上面是Android弹出对话框的代码,代码看起来十分清晰,通过查看源码发现它是用了建造者模式。那么下面就看一下它怎么把我们定制的需求显示出来的吧。()

查看AlertDialog的源码,发现它的内部有一个AlertController的变量

public class AlertDialog extends AppCompatDialog implements DialogInterface {

private AlertController mAlert;

.......
} 

进入AlertController,可以看到它的属性就是我们在代码里面设置的那些,所以在这里可以确定对话框显示的界面都是AlertController属性。

class AlertController {
private final Context mContext;
private final AppCompatDialog mDialog;
private final Window mWindow;

private CharSequence mTitle;
private CharSequence mMessage;
private ListView mListView;
private View mView;

private int mViewLayoutResId;

private int mViewSpacingLeft;
private int mViewSpacingTop;
private int mViewSpacingRight;
private int mViewSpacingBottom;
private boolean mViewSpacingSpecified = false;

private Button mButtonPositive;
private CharSequence mButtonPositiveText;
private Message mButtonPositiveMessage;

private Button mButtonNegative;
private CharSequence mButtonNegativeText;
private Message mButtonNegativeMessage;

private Button mButtonNeutral;
private CharSequence mButtonNeutralText;
private Message mButtonNeutralMessage;

private NestedScrollView mScrollView;

private int mIconId = 0;
private Drawable mIcon;

private ImageView mIconView;
private TextView mTitleView;
private TextView mMessageView;
private View mCustomTitleView;

private ListAdapter mAdapter;

private int mCheckedItem = -1;

private int mAlertDialogLayout;
private int mButtonPanelSideLayout;
private int mListLayout;
private int mMultiChoiceItemLayout;
private int mSingleChoiceItemLayout;
private int mListItemLayout;

private int mButtonPanelLayoutHint = AlertDialog.LAYOUT_HINT_NONE;

private Handler mHandler;

.........
}

Dialog是由它的静态内部类创建出来的,进入Builder发现它的内部也有一个AlertController.AlertParams的变量

 public static class Builder {

    private final AlertController.AlertParams P;

    .......
}

进入AlertController.AlertParams发现它实际就是AlertController的Builder,用于保存AlertController的属性值。

    public static class AlertParams {
    public final Context mContext;
    public final LayoutInflater mInflater;
    public int mIconId = 0;
    public Drawable mIcon;
    public int mIconAttrId = 0;
    public CharSequence mTitle;
    public View mCustomTitleView;
    public CharSequence mMessage;
    public CharSequence mPositiveButtonText;
    public DialogInterface.OnClickListener mPositiveButtonListener;
    public CharSequence mNegativeButtonText;
    public DialogInterface.OnClickListener mNegativeButtonListener;
    public CharSequence mNeutralButtonText;
    public DialogInterface.OnClickListener mNeutralButtonListener;
    public boolean mCancelable;
    public DialogInterface.OnCancelListener mOnCancelListener;
    public DialogInterface.OnDismissListener mOnDismissListener;
    public DialogInterface.OnKeyListener mOnKeyListener;
    public CharSequence[] mItems;

    ........
    }

到这里可以看出,我们的设置都是赋给AlertController的属性,所以到最后显示出来的也是AlertController里面的属性值。那么它是怎么显示到桌面的呢?

直接就看show()方法了

 public void show() {
    if (mShowing) {
        if (mDecor != null) {
            if (mWindow.hasFeature(Window.FEATURE_ACTION_BAR)) {
                mWindow.invalidatePanelMenu(Window.FEATURE_ACTION_BAR);
            }
            mDecor.setVisibility(View.VISIBLE);
        }
        return;
    }

    mCanceled = false;
    //如果没有创建就新建一个dialog视图
    if (!mCreated) {
        dispatchOnCreate(null);
    }

    onStart();
    mDecor = mWindow.getDecorView();

    if (mActionBar == null && mWindow.hasFeature(Window.FEATURE_ACTION_BAR)) {
        final ApplicationInfo info = mContext.getApplicationInfo();
        mWindow.setDefaultIcon(info.icon);
        mWindow.setDefaultLogo(info.logo);
        mActionBar = new WindowDecorActionBar(this);
    }

    WindowManager.LayoutParams l = mWindow.getAttributes();
    if ((l.softInputMode
            & WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) == 0) {
        WindowManager.LayoutParams nl = new WindowManager.LayoutParams();
        nl.copyFrom(l);
        nl.softInputMode |=
                WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION;
        l = nl;
    }
    try {
        mWindowManager.addView(mDecor, l);
        mShowing = true;

        sendShowMessage();
    } finally {
    }
}

我们跟着 dispatchOnCreate(null)这方法一直找到Dialog类的Oncreate方法,可以看出它是交给子类来实现的。

protected void onCreate(Bundle savedInstanceState) {
}

既然是交给子类实现,那就找到AlertDialog的Oncreate方法

 @Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    mAlert.installContent();
}

可以发现,最终还是到mAlert.installContent()这里来,进入这个方法

 public void installContent() {
    final int contentView = selectContentView();
    mDialog.setContentView(contentView);
    setupView();
}

可以看出Dialog最后显示的界面就是contentView ,进入selectContentView()这个方法

private int selectContentView() {
    if (mButtonPanelSideLayout == 0) {
        return mAlertDialogLayout;
    }
    if (mButtonPanelLayoutHint == AlertDialog.LAYOUT_HINT_SIDE) {
        return mButtonPanelSideLayout;
    }
    return mAlertDialogLayout;
}

所以正常情况下就返回mAlertDialogLayout这个布局,它是android定义好的一个布局

      mAlertDialogLayout = a.getResourceId(R.styleable.AlertDialog_android_layout, 0);

那么我们设置的那些参数都去哪了?它都在 setupView()这个方法里面设置进去了,这里就不一一探究,读者可自行查看源码。

下面就用建造者模式模仿一个AlertDialog吧

先创建一个AlertController,它有一个内部类AlertParams,代码如下

public class AlertController {


private String title;

private String content;

private String footer;

public AlertController() {

}

public void setTitle(String title) {
    this.title = title;
}

public void setContent(String content) {
    this.content = content;
}

public void setFooter(String footer) {
    this.footer = footer;
}

public void Show() {
    System.out.println(this);
}

@Override
public String toString() {
    return "AlertController [title=" + title + ", content=" + content + ", footer=" + footer + "]";
}


public static class AlertParams{

    public String title;

    public String content;

    public String footer;

    public AlertParams() {

    }

    public void applyto(AlertController dialog) {
        if (title != null) {
            dialog.setTitle(title);
        }

        if (content != null) {
            dialog.setContent(content);
        }

        if (footer != null) {
            dialog.setFooter(footer);
        }

    }
  }
}

然后再创建一个AlertDialog类,它有一个内部类Builder,代码如下

public class AlertDialog {

private AlertController alertController;

public AlertDialog() {

    alertController = new AlertController();
}

public void show() {

    alertController.Show();
}

 public static class Builder{

 AlertController.AlertParams params;

    public Builder() {
        params = new AlertController.AlertParams();
    }

    public Builder setTitle(String title) {
        params.title = title;
        return this;
    }

    public Builder setContent(String content) {
        params.content = content;
        return this;
    }


    public Builder setFooter(String footer) {
        params.footer = footer;
        return this;

    }

    public AlertDialog create() {
        AlertDialog dialog = new AlertDialog();

        params.applyto(dialog.alertController); 

        return dialog;

    }
  }  
}

然后测试一下:

 public class Main {
    public static void main(String[] args) {

    new AlertDialog.Builder()
    .setTitle("this is title")
    .setContent("this is content")
    .create()
    .show();
    }
}

结果如下:
这里写图片描述

以上只是一种没有指挥者的建造者模式,现在对设计模式只是很浅层面的了解,只是让自己看一些框架源码的时候能够对它的架构更加清晰。至于更深层次的了解,要到做项目时发现自己代码的问题,从而联想起某种设计模式并对代码进行优化改造,我想那时候对某个设计模式的了解就更加深刻了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值