設計模式(二)AlertDialog中的建造者模式

1、基本概念:

一、定義:

將一個複雜對象構建與它的表示分離,使得一樣的構建過程能夠建立不一樣的表示。bash

二、適用場景:

  • 多個組成部分,均可以裝配到同一個對象,可是產生的結果不相同
  • 相同的方法,不一樣的執行順序,產生不一樣的事件結果
  • 產品特別複雜,參數比較多的狀況 例:電腦含有不少零配件,能夠算是一個複雜對象。其中內存卡,主板、CPU等都是電腦的組成部分,若是構建一臺電腦,不須要知道是如何組裝的,只須要提供所須要的零配件型號,此時就能夠用構建者模式。

三、優勢:

  • 封裝性好,可使使用者沒必要知道內部組成的細節
  • 建造者獨立,容易擴展

四、類圖:

  • Director:導演類,負責安排模塊順序,通知Builder開始構建
  • Builder:抽象Builder類,規範產品的組建
  • ConcreteBuilder:構造者實現類,實現抽象類的全部方法,而且返回一個組建好的對象
  • Product:產品類

2、實例:

一、產品實體類:

public class Computer {
    private String cpu;
    private String mainBoard;
    private String ram;

    public String getCpu() {
        return cpu;
    }

    public void setCpu(String cpu) {
        this.cpu = cpu;
    }

    public String getMainBoard() {
        return mainBoard;
    }

    public void setMainBoard(String mainBoard) {
        this.mainBoard = mainBoard;
    }

    public String getRam() {
        return ram;
    }

    public void setRam(String ram) {
        this.ram = ram;
    }
}
複製代碼
二、抽象Builder:
public abstract class Builder {
    public abstract void buildCpu(String cpu);
    public abstract void buildMainBoard(String mainBoard);
    public abstract void buildRam(String ram);
    public abstract Computer build();
}
複製代碼

三、Builder實現類:

public class ComputerBuilder extends Builder {
    private Computer mComputer = new Computer();
    
    @Override
    public void buildCpu(String cpu) {
        mComputer.setCpu(cpu);
    }

    @Override
    public void buildMainBoard(String mainBoard) {
        mComputer.setMainBoard(mainBoard);
    }

    @Override
    public void buildRam(String ram) {
        mComputer.setRam(ram);
    }

    @Override
    public Computer build() {
        return mComputer;
    }
}
複製代碼

四、導演類:

起到封裝的做用,避免深刻到Builder內部的具體實現。能夠傳入不一樣的Builder實現對象。app

public class ComputerDirector {
    private Builder mBuilder;

    private ComputerDirector(Builder builder) {
        this.mBuilder = builder;
    }

    public Computer createComputer(String cpu, String mainBoard, String ram) {
        mBuilder.buildCpu(cpu);
        mBuilder.buildMainBoard(mainBoard);
        mBuilder.buildRam(ram);
        return mBuilder.build();
    }
}
複製代碼

五、客戶端調用:

public class ComputerTest {
    public static void main(String[] args){
        Builder builder = new ComputerBuilder();
        ComputerDirector director = new ComputerDirector(builder);
        director.createComputer("i3","my board", "4g");
    }
}
複製代碼

在實際使用過程當中,有時會將Director進行省略,由調用者選擇部分參數進行設置ide

3、AlertDialog

一、Builder

public static class Builder {ui

private final AlertController.AlertParams P;

    public Builder(Context context) {
        this(context, resolveDialogTheme(context, 0));
    }

    public Builder(Context context, int themeResId) {
        P = new AlertController.AlertParams(new ContextThemeWrapper(
                context, resolveDialogTheme(context, themeResId)));
    }
   
    public Builder setTitle(@StringRes int titleId) {
        P.mTitle = P.mContext.getText(titleId);
        return this;
    }

    public Builder setCustomTitle(View customTitleView) {
        P.mCustomTitleView = customTitleView;
        return this;
    }

    public Builder setMessage(@StringRes int messageId) {
        P.mMessage = P.mContext.getText(messageId);
        return this;
    }
    ......

    public AlertDialog create() {
        // Context has already been wrapped with the appropriate theme.
        final AlertDialog dialog = new AlertDialog(P.mContext, 0, false);
        //調用了AlertParams的apply方法
        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;
    }

    public AlertDialog show() {
        final AlertDialog dialog = create();
        dialog.show();
        return dialog;
    }

}
複製代碼

Builder中定義了一些set方法用來設置Dialog的參數,Builder方法內部是給AlertController.AlertParams進行參數賦值this

二、AlertDialog.AlertParams

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 AlertParams(Context context) {
        mContext = context;
        mCancelable = true;
        mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }
    //將參數賦值給了Dialog
    public void apply(AlertController dialog) {
        if (mCustomTitleView != null) {
            dialog.setCustomTitle(mCustomTitleView);
        } else {
            if (mTitle != null) {
                dialog.setTitle(mTitle);
            }
            if (mIcon != null) {
                dialog.setIcon(mIcon);
            }
            if (mIconId != 0) {
                dialog.setIcon(mIconId);
            }
            if (mIconAttrId != 0) {
                dialog.setIcon(dialog.getIconAttributeResId(mIconAttrId));
            }
        }
        if (mMessage != null) {
            dialog.setMessage(mMessage);
        }
        ......
    }
} 
複製代碼

三、基本使用

AlertDialog.Builder builder = new AlertDialog.Builder(this);
        // 設置參數
builder.setTitle("")
    .setIcon(R.drawable.ic_launcher)
    .setMessage("");
builder.create().show();
複製代碼
  • 先建立一個Builder對象,經過Builder進行參數設置
  • 內部會將這些參數傳遞給AlertDialog.AlertParams
  • 在調用create方法時,AlertDialog.AlertParams再將參數設置給AlertDialog
  • 最終經過show方法顯示dialog

Builder模式一般做爲配置類的構造器將配置的構造和表示分離,而且經過調用鏈實現,使代碼調用更簡潔。spa

相關文章
相關標籤/搜索