android 设计者模式,Android小知识-理解设计模式中的建造者模式

本平台的文章更新会有延迟,大家可以关注微信公众号-顾林海,包括年底前会更新kotlin由浅入深系列教程,目前计划在微信公众号进行首发,如果大家想获取最新教程,请关注微信公众号,谢谢

建造者模式的定义是:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。也就是说将构建过程和部件的表示隔离开,用户可以在不知道内部构建细节的情况下,对对象的构造流程进行相应的控制,比如在Android中典型的Builder模式就是AlerDialog.Builder类。

先看下UML图:

AAffA0nNPuCLAAAAAElFTkSuQmCC

image

模型图上的四个角色介绍如下:builder:为创建一个产品对象的各个部件指定抽象接口。

ConcreteBuilder:实现Builder的接口以构造和装配该产品的各个部件,定义并明确它所创建的表示,并 提供一个检索产品的接口。

Director:构造一个使用Builder接口的对象。

Product:表示被构造的复杂对象。ConcreteBuilder创建该产品的内部表示并定义它的装配过程,包含定义组成部件的类,包括将这些部件装配成最终产品的接口。package com.apk.administrator.loadapk;/**

* Product

* 具体的产品

*/public class Person {

private String head;    private String body;    private String foot;    public String getHead() {        return head;

}    public void setHead(String head) {        this.head = head;

}    public String getBody() {        return body;

}    public void setBody(String body) {        this.body = body;

}    public String getFoot() {        return foot;

}    public void setFoot(String foot) {        this.foot = foot;

}

}package com.apk.administrator.loadapk;/**

* Builder

* 产品构建的抽象接口

*/public interface PersonBuilder {    void buildHead();    void buildBody();    void buildFoot();    Person buildPerson();

}/**

* Director

* 建造者

*/public class PersonDirector {

public Person constructPerson(PersonBuilder pb) {

pb.buildHead();

pb.buildBody();

pb.buildFoot();        return pb.buildPerson();

}

}package com.apk.administrator.loadapk;/**

* ConcreteBuilder

* 具体建造工具(创建一个男人)

*/public class ManBuilder implements PersonBuilder {

Person person;    public ManBuilder() {

person = new Person();

}    public void buildBody() {

person.setBody("建造男人的身体");

}    public void buildFoot() {

person.setFoot("建造男人的脚");

}    public void buildHead() {

person.setHead("建造男人的头");

}    public Person buildPerson() {        return person;

}

}package com.apk.administrator.loadapk;public class Test {    public static void main(String[] args) {

PersonDirector pd = new PersonDirector();

Person person = pd.constructPerson(new ManBuilder());

System.out.println(person.getBody());

System.out.println(person.getFoot());

System.out.println(person.getHead());

}

}

上面代码中最终的目的是要创建一个男人的对象,具体怎么创建使用者不关心,只需要通过建造者PersonDirector创建一个对象,什么对象?ManBuilder对象,这样男人对象就创建出来了。

案例:Dialog的封装

在封装Dialog时,会使用静态内部类Builder对Diloag的标题、内容、按钮以及事件监听进行配置,并通过CommonDialog类展示。

可以看出这是很典型的Builder模式,在配置参数时返回的是Builder本身,这样的话可以通过链式调用,使代码的可读性大大提高。由于封装的是Dialog,因此,Builder类会去继承Dialog来自定义Dialog。下面贴出完整的Dialog封装类:package com.glh.getproject.view;import android.app.Dialog;import android.content.Context;import android.os.Bundle;import android.text.TextUtils;import android.view.Gravity;import android.view.View;import android.view.View.OnClickListener;import android.view.WindowManager;import android.widget.TextView;import com.glh.getproject.R;public class CommonDialog {    private Builder mBuilder;    private CommonDialog(Builder builder) {        this.mBuilder = builder;

}    public void show() {

mBuilder.showDialog();

}    public static class Builder extends Dialog implements OnClickListener {        private TextView tv_title;        private TextView tv_left;        private TextView tv_right;        private TextView tv_info;        private DialogListener mDialogListener;        private String title;        private String info;        private String strLeftBtn;        private String strRightBtn;        public interface DialogListener {            void ok();            void cancel();

}        void showDialog() {

show();

}        @Override

protected void onCreate(Bundle savedInstanceState) {            super.onCreate(savedInstanceState);

setContentView(R.layout.dialogl_info_show);

initUI();

initEvent();

initViewStatus();

}        private void initUI() {

tv_title = findViewById(R.id.tv_title);

tv_left = findViewById(R.id.tv_left);

tv_right = findViewById(R.id.tv_right);

tv_info = findViewById(R.id.tv_info);

}        private void initViewStatus() {            if (!TextUtils.isEmpty(title)) {

tv_title.setText(title);

}            if (!TextUtils.isEmpty(info)) {

tv_info.setText(info);

}            if (!TextUtils.isEmpty(strLeftBtn)) {

tv_left.setText(strLeftBtn);

} else {

tv_left.setText("确定");

}            if (!TextUtils.isEmpty(strRightBtn)) {

tv_right.setText(strRightBtn);

} else {

tv_right.setText("取消");

}

}        private void initEvent() {

tv_left.setOnClickListener(this);

tv_right.setOnClickListener(this);

}        @Override

public void onClick(View v) {            switch (v.getId()) {                case R.id.tv_left:                    if (mDialogListener != null) {

dismiss();

mDialogListener.ok();

}                    break;                case R.id.tv_right:                    if (mDialogListener != null) {

dismiss();

mDialogListener.cancel();

}                    break;                default:                    break;

}

}        public Builder(Context context) {            super(context, R.style.MessageBox);

setCanceledOnTouchOutside(false);

getWindow().setBackgroundDrawableResource(android.R.color.transparent);

WindowManager.LayoutParams wl = getWindow().getAttributes();

wl.gravity = Gravity.CENTER;

getWindow().setAttributes(wl);

}        public Builder setListener(DialogListener listener) {            this.mDialogListener = listener;            return this;

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

}        public Builder setInfo(String info) {            this.info = info;            return this;

}        public Builder setLeftButtonTitle(String title) {            this.strLeftBtn = title;            return this;

}        public Builder setRightButtonTitle(String title) {            this.strRightBtn = title;            return this;

}        public CommonDialog build() {            return new CommonDialog(this);

}

}

}

相关的Style:

true

true

@null

center

layout文件:<?xml  version="1.0" encoding="utf-8"?>

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:background="@android:color/transparent">

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_centerInParent="true"

android:layout_marginLeft="20dp"

android:layout_marginRight="20dp"

android:background="@drawable/dialog_background_shape"

android:paddingLeft="16dp"

android:paddingRight="16dp">

android:id="@+id/ll_title"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_centerHorizontal="true"

android:layout_marginTop="20dp"

android:gravity="center_horizontal"

android:orientation="vertical">

android:id="@+id/tv_title"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:gravity="center"

android:lineSpacingExtra="2dp"

android:textColor="@color/title"

android:textSize="17sp"

android:visibility="visible" />

android:id="@+id/tv_info"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:gravity="center"

android:lineSpacingExtra="2dp"

android:paddingTop="20dp"

android:textColor="@color/title"

android:textSize="17sp"

android:visibility="visible" />

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_below="@id/ll_title"

android:layout_centerHorizontal="true"

android:layout_marginTop="25dp"

android:gravity="center"

android:orientation="horizontal"

android:paddingBottom="20dp"

android:visibility="visible">

android:id="@+id/tv_left"

android:layout_width="0dp"

android:layout_height="wrap_content"

android:layout_marginRight="5dp"

android:layout_weight="1"

android:background="@drawable/red_button_shape"

android:gravity="center"

android:paddingBottom="7dp"

android:paddingLeft="30dp"

android:paddingRight="30dp"

android:paddingTop="7dp"

android:textColor="@color/white"

android:textSize="14sp"

android:visibility="visible" />

android:id="@+id/tv_right"

android:layout_width="0dp"

android:layout_height="wrap_content"

android:layout_marginLeft="5dp"

android:layout_weight="1"

android:background="@drawable/gray_button_shape"

android:gravity="center"

android:paddingBottom="7dp"

android:paddingLeft="30dp"

android:paddingRight="30dp"

android:paddingTop="7dp"

android:textColor="@color/white"

android:textSize="14sp"

android:visibility="visible" />

整个Dialog的布局背景和按钮都是通过自定义Shape来实现的。

dialog_background_shape:<?xml  version="1.0" encoding="utf-8"?>

red_button_shape:<?xml  version="1.0" encoding="utf-8"?>

gray_button_shape:<?xml  version="1.0" encoding="utf-8"?>

在Activity中使用:public void showDialog() {

CommonDialog commonDialog = new CommonDialog.Builder(this)

.setListener(new CommonDialog.Builder.DialogListener() {                @Override

public void ok() {

Toast.makeText(MainActivity.this, "正在更新...", Toast.LENGTH_SHORT).show();

}                @Override

public void cancel() {

}

}).setTitle("更新通知")

.setInfo("当前版本暂不可用,请下载最新版本,以便享受优质内容。")

.setLeftButtonTitle("知道了")

.setRightButtonTitle("不需要")

.build();

commonDialog.show();

}

案例二:PopupWindow的封装package com.glh.getproject.view;import android.content.Context;import android.graphics.drawable.BitmapDrawable;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.PopupWindow;import android.widget.TextView;import com.glh.getproject.R;/**

* 更新弹框

* Created by glh on 2017-05-09.

*/public class UpdateDialog {    private PopupWindow mPopupWindow;    private Builder mBuilder;    private UpdateDialog(Builder builder) {        this.mBuilder = builder;

View mPopupLayout = builder.mPopupLayout;        this.mPopupWindow = new PopupWindow(mPopupLayout, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, true);        this.mPopupWindow.setContentView(mPopupLayout);        this.mPopupWindow.setOutsideTouchable(true);        this.mPopupWindow.setFocusable(true);        this.mPopupWindow.setBackgroundDrawable(new BitmapDrawable());        this.mPopupWindow.setOnDismissListener(new PopupWindow.OnDismissListener() {            @Override

public void onDismiss() {                if (mBuilder.mCloseListener != null) {

mBuilder.mCloseListener.onClose();

}

}

});        this.mPopupWindow.update();

}    public void dismiss() {        if (!mPopupWindow.isShowing()) {            return;

}

mPopupWindow.dismiss();

}    public void showAtLocation(View parent, int gravity, int x, int y) {

mPopupWindow.showAtLocation(parent, gravity, x, y);

}    public static class Builder {        private View mPopupLayout;        private TextView tv_title;        private TextView tv_left;        private TextView tv_right;        private TextView tv_info;        private UpgradeListener mUpgradeListener;        private CloseListener mCloseListener;        private void initEvent() {

tv_left.setOnClickListener(new View.OnClickListener() {                @Override

public void onClick(View view) {                    if (mUpgradeListener != null) {

mUpgradeListener.upgrade(true);

}

}

});

tv_right.setOnClickListener(new View.OnClickListener() {                @Override

public void onClick(View view) {                    if (mUpgradeListener != null) {

mUpgradeListener.upgrade(false);

}

}

});

}        public interface UpgradeListener {            void upgrade(boolean upgrade);

}        public interface CloseListener {            void onClose();

}        public Builder(Context context) {

mPopupLayout = LayoutInflater.from(context).inflate(R.layout.dialogl_info_show, null, true);

tv_title = mPopupLayout.findViewById(R.id.tv_title);

tv_left = mPopupLayout.findViewById(R.id.tv_left);

tv_right = mPopupLayout.findViewById(R.id.tv_right);

tv_info = mPopupLayout.findViewById(R.id.tv_info);

initEvent();

}        public Builder setUpgradeListener(UpgradeListener listener) {            this.mUpgradeListener = listener;            return this;

}        public Builder setCloseListener(CloseListener listener) {            this.mCloseListener = listener;            return this;

}        public Builder setTitle(String title) {            this.tv_title.setText(title);            return this;

}        public Builder setInfo(String info) {            this.tv_info.setText(info);            return this;

}        public Builder setLeftButtonTitle(String title) {            this.tv_left.setText(title);            return this;

}        public Builder setRightButtonTitle(String title) {            this.tv_right.setText(title);            return this;

}        public UpdateDialog build() {            return new UpdateDialog(this);

}

}

}

layout文件和Dialog的布局文件一样,这里就不贴出来了。

在Activity的使用:private UpdateDialog commonDialog;private void showPopupWindow() {    if (null == commonDialog) {

commonDialog = new UpdateDialog.Builder(this)

.setUpgradeListener(new UpdateDialog.Builder.UpgradeListener() {                    @Override

public void upgrade(boolean upgrade) {

commonDialog.dismiss();                        if (upgrade) {

Toast.makeText(MainActivity.this, "正在更新...", Toast.LENGTH_SHORT).show();

}

}

}).setCloseListener(new UpdateDialog.Builder.CloseListener() {                    @Override

public void onClose() {

Toast.makeText(MainActivity.this, "对话框关闭了", Toast.LENGTH_SHORT).show();

}

}).setTitle("更新通知")

.setInfo("当前版本暂不可用,请下载最新版本,以便享受优质内容。")

.setLeftButtonTitle("知道了")

.setRightButtonTitle("不需要")

.build();

}

commonDialog.showAtLocation(mGroup, Gravity.CENTER, 0, 0);

}

作者:顾林海

链接:https://www.jianshu.com/p/0a95b4329bff

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值