构建者模式在android端中的实际应用

试想一种需求,有一个简单的Bean类,Bean类里有10个属性,但是我们初始化的时候仅仅想设置2个属性,可能会想到构造函数,但是如果需求升级,让我们设置4个,6个属性,如果用构造函数那代码会过于臃肿,此外频繁的set设置属性,调用的地方代码也比较多且可读性不太好,在这时候可以采用构建者模式了。

建造者模式的定义: 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

经典构建者模式有以下几个角色:

构建者角色、指导者、产品角色。

构建者模式的优缺点:

在创建者模式中,客户端不再负责对象的创建与组装,而是把这个对象创建的责任交给其具体的创建者类,把组装的责任交给组装类,客户端只负责对象的调用,从而明确了各个类的职责。

虽然利用创建者模式可以创建出不同类型的产品,但是如果产品之间的差异巨大,则需要编写多个创建者类才能实现,如果这是结合工厂模式更好。

我们以汉堡包为例,通过代码说下构建者模式:

1.产品抽象角色:

/**
 * 经典构建者模式-产品抽象角色
 * Created by wangmaobo on 2019/3/25.
 */
public abstract class HamBurg {
    protected String bread;
    protected String vegetable;
    protected float prize;

    public void setBread(String name) {
        this.bread = name;
    }

    public abstract void setPrize();

    public void setVegetable(String vegetable) {
        this.vegetable = vegetable;
    }

    @Override
    public String toString() {
        return "HamBurg{" +
                "bread='" + bread + '\'' +
                ", vegetable='" + vegetable + '\'' +
                ", prize='" + prize + '\'' +
                '}';
    }
}

2.产品具体角色:

/**
 * 经典构建者模式-具体构建者类
 * Created by wangmaobo on 2019/3/25.
 */
public class ChineseHamBugeBuilder extends Builder {
    private HamBurg mHamBurg = new ChineseHamBurg();

    @Override
    public void buildBread(String bread) {
        mHamBurg.setBread(bread);
    }

    @Override
    public void buildVegetable(String vegetable) {
        mHamBurg.setVegetable(vegetable);
    }

    @Override
    public void buildPrize() {
        mHamBurg.setPrize();
    }

    @Override
    public HamBurg create() {
        return mHamBurg;
    }
}

3.抽象构建者角色:

/**
 * 经典构建者模式-抽象构建者类
 * Created by wangmaobo on 2019/3/25.
 */
public abstract class Builder {
    public abstract void buildBread(String bread);

    public abstract void buildVegetable(String vegetable);

    public abstract void buildPrize();

    public abstract HamBurg create();

}

4.具体构建者角色:

/**
 * 经典构建者模式-具体构建者类
 * Created by wangmaobo on 2019/3/25.
 */
public class ChineseHamBugeBuilder extends Builder {
    private HamBurg mHamBurg = new ChineseHamBurg();

    @Override
    public void buildBread(String bread) {
        mHamBurg.setBread(bread);
    }

    @Override
    public void buildVegetable(String vegetable) {
        mHamBurg.setVegetable(vegetable);
    }

    @Override
    public void buildPrize() {
        mHamBurg.setPrize();
    }

    @Override
    public HamBurg create() {
        return mHamBurg;
    }
}

5.导演角色:


/**
 * 经典构建者模式-导演组装类
 * Created by wangmaobo on 2019/3/25.
 */
public class Director {
    Builder mBuilder;

    public Director(Builder builder) {
        mBuilder = builder;
    }

    public Builder construct(String bread, String vegetable) {
        mBuilder.buildBread(bread);
        mBuilder.buildVegetable(vegetable);
        mBuilder.buildPrize();
        return mBuilder;
    }
}

调用:

        Builder builder = new ChineseHamBugeBuilder();
        Director director = new Director(builder);
        director.construct("chinese bread", "carrot");
        HamBurg hamBurg = builder.create();
        Log.e("classic hamburg", "中国汉堡包信息:" + hamBurg.toString());

实际上,我们可以将经典构建者模式进行适当调整,在没有批量处理的需求下,调用更加方便。

将构建者角色类稍加改进:

/**
 * 经典构建者模式-具体构建者类
 * Created by wangmaobo on 2019/3/25.
 */
public class ChineseHamBugeBuilder extends Builder {
    private HamBurg mHamBurg = new ChineseHamBurg();

    @Override
    public Builder buildBread(String bread) {
        mHamBurg.setBread(bread);
        return this;
    }

    @Override
    public Builder buildVegetable(String vegetable) {
        mHamBurg.setVegetable(vegetable);
        return this;
    }

    @Override
    public Builder buildPrize() {
        mHamBurg.setPrize();
        return this;
    }

    @Override
    public HamBurg create() {
        return mHamBurg;
    }
}

调用:

HamBurg hamBurg1 = new ChineseHamBugeBuilder()
                .buildBread("chinese bread")
                .buildVegetable("carrot")
                .buildPrize()
                .create();
Log.e("improve hamburg", "中国汉堡" + hamBurg1.toString());

实际上我们还可以省去抽象类,及导演类,将构建者Builder类作为产品的内部类,类似实现的比如开源框架Retrofit,具体调用:


            OkHttpClient.Builder builder = new OkHttpClient.Builder()
                    .connectTimeout(15, TimeUnit.SECONDS)
                    .readTimeout(20, TimeUnit.SECONDS)
                    .writeTimeout(20, TimeUnit.SECONDS)
                    .retryOnConnectionFailure(false)
                    .addInterceptor(interceptor);
            OkHttpClient client = builder.build();
            retrofitInstance = new Retrofit.Builder()
                    .baseUrl(BASEURL)
                    .client(client)
                    .addConverterFactory(GsonConverterFactory.create())
                    .build();

当然实际项目开发中我们甚至可以省略构建者角色,参考RxJava的链式调用风格,将所需要的属性设置直接放到产品角色类里面,比如之前我封装过的万能适配器的ViewHolder类:

public class ViewHolder extends RecyclerView.ViewHolder {
        private final SparseArray<View> mViews;
        private View itemView;

        public ViewHolder(View itemView) {
            super(itemView);
            mViews = new SparseArray<>();
            this.itemView = itemView;
            this.itemView.setOnClickListener(v -> {
                onItemClick(getAdapterPosition());
                if (mOnItemClickListener != null)
                    setOnItemClick(v, getAdapterPosition());
            });
            setTextChangedListener(this, itemView);
            setRatingBarListener(this, itemView);
        }

        public <T extends View> T getView(int viewId) {
            View view = mViews.get(viewId);
            if (view == null) {
                view = itemView.findViewById(viewId);
                mViews.put(viewId, view);
            }
            return (T) view;
        }

        public ViewHolder setText(int viewId, String text) {
            if (TextUtils.isEmpty(text)) {
                text = "";
            }
            TextView tv = getView(viewId);
            tv.setText(text);
            return this;
        }

        /**
         * 如果text为空,显示“--”
         *
         * @param viewId
         * @param text
         * @return
         */
        public ViewHolder setTextNotNull(int viewId, String text) {
            if (TextUtils.isEmpty(text)) {
                text = "--";
            }
            TextView tv = getView(viewId);
            tv.setText(text);

            return this;
        }

        public ViewHolder setTextHint(int viewId, String hint) {
            if (TextUtils.isEmpty(hint)) {
                return this;
            }
            TextView tv = getView(viewId);
            tv.setHint(hint);
            return this;
        }

        public ViewHolder setBackground(int viewId, int drawableId) {
            View view = getView(viewId);
            view.setBackground(mContext.getResources().getDrawable(drawableId));
            return this;
        }

        /**
         * 如果text为空,控件隐藏
         *
         * @param viewId
         * @param text
         * @return
         */
        public ViewHolder setTextAndView(int viewId, String text) {
            TextView tv = getView(viewId);
            if (TextUtils.isEmpty(text)) {
                tv.setVisibility(View.GONE);
            } else {
                tv.setText(text);
                tv.setVisibility(View.VISIBLE);
            }
            return this;
        }

        public ViewHolder setProjectName(int viewId, String text) {
            TextView tv = getView(viewId);
            if (CommonUtils.IsNull(Constant.project_id) && !CommonUtils.IsNull(text)) {
                tv.setVisibility(View.VISIBLE);
                tv.setText(text);
            } else {
                tv.setVisibility(View.GONE);
            }
            return this;
        }

        public ViewHolder setTextColor(int viewId, int textColorId) {
            TextView tv = getView(viewId);
            tv.setTextColor(textColorId);
            return this;
        }

        public ViewHolder setImage(int viewId, Object params) {
            ImageView iv = getView(viewId);
            if (params instanceof String) {
                //自己写加载图片的逻辑-默认的加载模式
                GlideUtils.loadImageViewCircle(mContext, params.toString(),
                        getView(viewId), R.mipmap.image_loading_icon);
            } else if (params instanceof Integer) {
                iv.setImageResource((int) params);
            } else if (params instanceof Bitmap) {
                iv.setImageBitmap((Bitmap) params);
            } else if (params instanceof Drawable) {
                iv.setImageDrawable((Drawable) params);
            } else {
                try {
                    throw new Exception("params is wrong!");
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            return this;
        }

        public ViewHolder setCircleImage(int viewId, String url, String name) {
            GlideUtils.loadHeadImg(mContext, url, name, getView(viewId));
            return this;
        }

        public ViewHolder setClickListener(int viewId) {
            View v = getView(viewId);
            v.setOnClickListener(v1 -> onSingleViewClick(v1, getAdapterPosition()));
            return this;
        }

        public ViewHolder setVisible(int viewId) {
            View v = getView(viewId);
            v.setVisibility(View.VISIBLE);
            return this;
        }

        public ViewHolder setInVisible(int viewId) {
            View v = getView(viewId);
            v.setVisibility(View.GONE);
            return this;
        }

        public int getCurrentPosition() {
            return getAdapterPosition();
        }

    }

调用举例:

holder.setTextNotNull(R.id.tv_introduce, content.eventTitle)
        .setTextNotNull(R.id.tv_urgency, content.urgentName)
        .setTextNotNull(R.id.tv_question, content.eventDescribe)
        .setTextNotNull(R.id.tv_createPerson, "创建人")
        .setTextNotNull(R.id.tv_createTime, create_time)
        .setTextNotNull(R.id.tv_startTime, start_time)
        .setTextNotNull(R.id.tv_endTime, end_time)
        .setTextNotNull(R.id.tv_notice, content.eventStateName)
        .setTextNotNull(R.id.tv_work_type, content.eventSourceName);

项目中能用到此模式的地方举例:

1.自定义View里,可以选择性的组装View的属性,避免了各种构造函数的创建;

2.各种Bean类里,比如EventBusBean,数据Bean类;

3.实现某一个大的功能的框架。

ps:开发模式是死的,人是活的,任何一种设计模式都有其优缺点,我们可以根据自己的产品需求,获取其优点,让开发效率及代码可读性更高一点,尽可能“取其精华,去其糟粕”。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
建造者模式实际项目常见的应用场景包括: 1. 构建复杂的对象:当需要创建一个复杂的对象,该对象由多个部分组成,并且构建过程较为复杂时,可以使用建造者模式。例如,创建一个包含多个属性和关联对象的订单对象,或者创建一个包含多个组件和配置选项的UI界面。 2. 配置对象的不同表示:当需要根据不同的需求或条件创建不同的对象表示时,可以使用建造者模式。例如,在一个电商平台上,根据用户的选择和配置项,可以构建多个不同种类的商品对象。 3. 避免过多的构造函数参数:当一个对象拥有大量属性或参数,并且可能存在多种组合方式时,使用多个构造函数会导致构造函数的参数列表过长和代码的可读性下降。通过使用建造者模式,可以将对象的构建过程分解为多个步骤,避免过多的构造函数参数。 4. 实现对象的组装和配置:建造者模式可以实现对象的灵活组装和配置。通过设置不同的属性和调用不同的构建方法,可以在构建过程对对象进行细粒度的控制和配置。例如,在一个游戏,可以根据玩家的选择和游戏规则来构建不同类型的角色对象。 5. 实现对象的可伸缩性和可扩展性:使用建造者模式可以将对象的构建过程与表示分离,使得在不修改已有代码的情况下,可以引入新的具体建造者来创建新的对象表示。这提供了更好的可伸缩性和可扩展性。 总之,建造者模式实际项目常用于构建复杂对象、配置不同表示、避免过多构造函数参数、实现对象的组装和配置,以及实现对象的可伸缩性和可扩展性。它能够提供更好的灵活性和可维护性,使得代码结构清晰,并且方便地创建和配置对象。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值