android 源码设计模式读书笔记(一)

这是第二次读这本书了 有时感觉讲的事真的不错
第一次读完什么都没有留下 除了已经不知道哪去的源码 只剩下诗和远方
主要是长时间不看你 改忘得都差不多了 现在有时间在读一遍 希望 可以把这本书的读书笔记一直写下去
大概一中午时间读完了 第一章 最大的感慨就是小民最开始真的是碰到一个非常优秀又严格的主管 这真是一件让人羡慕 有难以达成的事 作为一个小场的程序员 我们只能在自己的摸索中前进了 闲话与羡慕的话不多少了 第一章的读书笔记
为他单开一张 真的是感觉他才是本书最重要的章节
学习设计模式首先要学习的是 六大原则
设计的六大原则:
(一)单一职责原则:就一个类而言应该仅有一个引起他变化的原因
(二)开闭原则:软件中的类应该是对扩展开放的,对修改是封闭的。
(三)里氏置换原则:引用基类的地方必须能够透明的使用的的子类对象(感觉还没写过不能的)
优点:(1) 代码重用,减少创建类的成本,每个子类都拥有父类的实现方法
(2)子类与父类相似,但由于父类有区别
(3)提高代码的可扩展性
缺点:(1)继承是侵入性的只要继承,就必须拥有父类所有的方法和属性
(2)可能造成代码冗余,灵活性降低。
(四)依赖倒置原则:高层次的模块不依赖于低层次的模块的实现细节
它有这么几个关键点:
(1)高层模块不能依赖低层模块,两者都应该依赖于其抽象
(2)抽象不依赖于细节
(3)细节依赖于抽象
(五)接口隔离原则:类之间的关系应该建立在最小的接口只上
(六)迪米特原则:至于具有直接关系的类进行交互。
下面是自己在实践过程中的应用和思考
我们要写的是一个自定义组合View 它包括好几种类型
类型一

image.png

类型二
image.png

类型三
image.png

类型四
image.png

类型五
image.png

类型六
image.png

第一版
分析:我们需要建一个实体类来标识每一条的属性

public class TimeOneVouchers  {
    private String time;
    private String voucherNo;
    private String storeName;
}
创建一个LinearLayout来动态添加
public class OrderStoreUserView extends LinearLayout {
    // 当前状态为所有券都被使用
    public static final int SHOW_TYPE_ALL_USE = 0x0001;
    // 当前状态为有券未都被使用--(已使用)
    public static final int SHOW_TYPE_NO_ALL_USE = 0x0010;
    // 当前状态为所有券未都已经失效
    public static final int SHOW_TYPE_NO_ALL_FAILURE = 0x0100;
    // 当前状态为有券未都被使用--(已退款)
    public static final int SHOW_TYPE_NO_ALL_USE_REFUND = 0x0101;
    private Context mContext;
    private LinearLayout ll_use;
    private TextView tv_order_store_use_num;

    private TextView tv_use_store_time;
    private TextView use_store_time;
    private TextView tv_vouchers_store;
    private TextView vouchers_store;
    private TextView vouchers_num;
    private TextView tv_vouchers_num;

    public OrderStoreUserView(Context context) {
        this(context, null);
    }

    public OrderStoreUserView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public OrderStoreUserView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mContext = context;
        initView();
    }

    private void initView() {
        LayoutInflater.from(mContext).inflate(R.layout.layout_order_store_use, this, true);
        ll_use = findViewById(R.id.ll_use);
        tv_order_store_use_num = findViewById(R.id.tv_order_store_use_num);
    }

    /***
     *
     * @param type 当前使用券的显示状态 SHOW_TYPE_ALL_USE,SHOW_TYPE_NO_ALL_USE,SHOW_TYPE_NO_ALL_FAILURE
     * @param timeOneVouchersList
     */
    public void setViewType(int type, List<TimeOneVouchers> timeOneVouchersList) {
        for (int i = 0; i < timeOneVouchersList.size(); i++) {
            View view = LayoutInflater.from(mContext).inflate(R.layout.layout_item_store_use, null, false);
            initItemView(view);
            UserVouchers userVouchers = timeOneVouchersList.get(i);
            setCommonData(userVouchers);
            switch (type) {
                case SHOW_TYPE_ALL_USE:
                    setViewAllUse(i, timeOneVouchersList, userVouchers);
                case SHOW_TYPE_NO_ALL_USE:
                    tv_order_store_use_num.setText("已使用(" + timeOneVouchersList.size() + ")份");
                    break;
                case SHOW_TYPE_NO_ALL_FAILURE:
                    setViewGone();
                    tv_order_store_use_num.setText("已失效(" + timeOneVouchersList.size() + ")份");
                    break;
                case SHOW_TYPE_NO_ALL_USE_REFUND:
                    setViewGone();
                    tv_order_store_use_num.setText("已退款(" + timeOneVouchersList.size() + ")份");
                    break;
            }

            ll_use.addView(view);
        }
    }

    //设置公共数据
    private void setCommonData(UserVouchers userVouchers) {
        tv_vouchers_num.setText(userVouchers.getVouchersNum());
        tv_use_store_time.setText(userVouchers.getTime());
        tv_vouchers_store.setText(userVouchers.getStoreName());
    }

    //初始化View
    private void initItemView(View view) {
        use_store_time = view.findViewById(R.id.use_store_time);
        tv_use_store_time = view.findViewById(R.id.tv_use_store_time);

        tv_vouchers_store = view.findViewById(R.id.tv_vouchers_store);
        vouchers_store = view.findViewById(R.id.vouchers_store);

        vouchers_num = view.findViewById(R.id.vouchers_num);
        tv_vouchers_num = view.findViewById(R.id.tv_vouchers_num);
    }

    //只显示券码 并画中横线
    private void setViewGone() {
        tv_vouchers_num.getPaint().setFlags(Paint.STRIKE_THRU_TEXT_FLAG); //中划线
        tv_vouchers_store.setVisibility(GONE);
        vouchers_store.setVisibility(GONE);
        use_store_time.setVisibility(GONE);
        tv_use_store_time.setVisibility(GONE);
    }

    private void setViewAllUse(int i, List<TimeOneVouchers> timeOneVouchersList, UserVouchers userVouchers) {
        tv_vouchers_store.setVisibility(GONE);
        vouchers_store.setVisibility(GONE);
        tv_vouchers_num.getPaint().setFlags(Paint.STRIKE_THRU_TEXT_FLAG); //中划线
        if (i != 0) {
            if (TextUtils.equals(timeOneVouchersList.get(i - 1).getTime(), userVouchers.getTime())) {
                vouchers_num.setVisibility(INVISIBLE);
                use_store_time.setVisibility(GONE);
                tv_use_store_time.setVisibility(GONE);
            }
        }
    }
}

这个样子完全不用考虑设计模式的第一版就新鲜出炉 虽然不用考虑设计模式但是也是完全可用的
但是看完第一章 感觉和小民的第一版完工很像 只是人家是被主管哒回来了 而 我们只能自己思考。
然后在现实中我们有碰到了一个很现实的问题提 接口的开发居然的app的界面 慢 你没有办法确认接口给你类型是什么样子的 字段 是不是time,voucherNo,storeName这三个。这该怎么办呢?要是个有脾气的程序员 或者新手可能就 字段还没给了怎么写 ,然后就等接口处了在写吧 这的确个解决方法。但是不应该这样子啊,感觉有好多自定义View都可能使用的Bean他们不能重视按照所需要用的在去改源码吧;在这里我们就应该用到依赖倒置原则 作为一个实现类时不应改 依赖于另一个实现类的细节的,我们应该让他依赖于接口 然后我就这门改写
写一个接口
public interface UserVouchers {
//券的使用时间
String getTime();
// 券的使用店铺
String getStoreName();
// 券 码
String getVouchersNum();
}
然后把List<TimeOneVouchers> 改为List<UserVouchers > 这样好像就可以了
改写后的自定View类不子啊以来与原来的具体的实现Bean只依赖于 UserVouchers接口 我们只需要等接口下来不管字段是什么样子的 只需要复写这三个方法摊入相应的属性就行了。
虽然加了这面几句话就搞定了 但的确也是对面向对象的应用
这块优化后实际问题已经解决了,提交代码搞定。
虽然功能已经搞定了,但是我们来看一看还有没有其他不符合面向对象的地方继续优化
优化前我们的数据结构是这样的


image.png

根据setViewType(int type, List<UserVouchers> timeOneVouchersList)这个方法进来的参数来决定每个加载不同View的类型并赋值 明显就不符合了单一性原则
每次技师只要修改一部分的功能还要修改这个类的代码只明显是和他本身的功能无关
那我们就需要修改这个类的数据结构了
根据数据结构分析
先画了一下优化后的UML


image.png

这样谁不是更加清晰了呢
而且我问吧单个的功能分开是不就符合的 单一性与隔离性的原则
然后就可以开始优化代码 反正只要是符合6大原则 基本上都是设计模式
所以有些东西可以系统的想上面靠 有些不可以而已 比如说 自定义View的参数构造一般都会使用建造者模式等等 我们要是读完整本书 即使记不住具体的设计模式也一定要记住这个第一张的6大原则 只需要 我们在做功能的基础设计的时候网上面靠就就行了 就比如说我上上面的这种想法其实也就是一个泛指,就比如说我们在做前端 多种支付的时候也可以涉及到。
我发现这个类图画完只是一个预想 实际操作过程中 有余还有一写含有公共的方法
还有少的一些参数
最终修改类图为
image.png

1.完成接口
public interface ItemView {
  View setView(Context context, List<UserVouchers> userVouchers,int i, TextView tv_order_store_use_num);
  void  initItemView(View view);
  void setCommonData(UserVouchers userVouchers);
  void setViewType(List<UserVouchers> userVouchers, int i, TextView tv_order_store_use_num);
}
  1. 完成基类
public abstract class BaseItemView implements ItemView {

    public TextView tv_use_store_time;
    public TextView use_store_time;
    public TextView tv_vouchers_store;
    public TextView vouchers_store;
    public TextView vouchers_num;
    public TextView tv_vouchers_num;

    @Override
    public View setView(Context context, List<UserVouchers> userVouchers,int i,TextView tv_order_store_use_num) {
        View view = LayoutInflater.from(context).inflate(R.layout.layout_item_store_use, null, false);
        initItemView(view);
        setCommonData(userVouchers.get(i));
        setViewType(userVouchers,i,tv_order_store_use_num);
        return view;
    }

    @Override
    public void initItemView(View view) {


        use_store_time = view.findViewById(R.id.use_store_time);
        tv_use_store_time = view.findViewById(R.id.tv_use_store_time);

        tv_vouchers_store = view.findViewById(R.id.tv_vouchers_store);
        vouchers_store = view.findViewById(R.id.vouchers_store);

        vouchers_num = view.findViewById(R.id.vouchers_num);
        tv_vouchers_num = view.findViewById(R.id.tv_vouchers_num);
    }

    @Override
    public void setCommonData(UserVouchers userVouchers) {
        tv_vouchers_num.setText(userVouchers.getVouchersNum());
        tv_use_store_time.setText(userVouchers.getTime());
        tv_vouchers_store.setText(userVouchers.getStoreName());
    }


    //只显示券码 并画中横线
    public void setViewGone() {
        tv_vouchers_num.getPaint().setFlags(Paint.STRIKE_THRU_TEXT_FLAG); //中划线
        tv_vouchers_store.setVisibility(GONE);
        vouchers_store.setVisibility(GONE);
        use_store_time.setVisibility(GONE);
        tv_use_store_time.setVisibility(GONE);
    }


}

3.完成各个的实现类

public class AllUsersView extends BaseItemView {

    @Override
    public void setViewType(List<UserVouchers> userVouchers, int i, TextView tv_order_store_use_num) {
        tv_order_store_use_num.setText("已使用(" + userVouchers.size() + ")份");
        tv_vouchers_store.setVisibility(GONE);
        vouchers_store.setVisibility(GONE);
        tv_vouchers_num.getPaint().setFlags(Paint.STRIKE_THRU_TEXT_FLAG); //中划线
        if (i != 0) {
            if (TextUtils.equals(userVouchers.get(i - 1).getTime(), userVouchers.get(i).getTime())) {
                vouchers_num.setVisibility(INVISIBLE);
                use_store_time.setVisibility(GONE);
                tv_use_store_time.setVisibility(GONE);
            }
        }
    }
}

@Override
    public void setViewType(List<UserVouchers> userVouchers, int i, TextView tv_order_store_use_num) {
        tv_order_store_use_num.setText("已失效(" + userVouchers.size() + ")份");
        setViewGone();
    }


public class NoAllUserView extends BaseItemView {


    @Override
    public void setViewType(List<UserVouchers> userVouchers, int i, TextView tv_order_store_use_num) {
        tv_order_store_use_num.setText("已使用(" + userVouchers.size() + ")份");
    }
}



public class RefundView extends BaseItemView {


    @Override
    public void setViewType(List<UserVouchers> userVouchers, int i, TextView tv_order_store_use_num) {
        setViewGone();
        tv_order_store_use_num.setText("已退款(" + userVouchers.size() + ")份");
    }
}

4.修改调用

 for (int i = 0; i < UserVouchers.size(); i++) {
            ll_use.addView(itemView.setView(mContext, UserVouchers, i, tv_order_store_use_num));
        }

这样就改完了 这样就可以在需要改某个View是时候 具体的实体类就行了 不需要在修改OrderStoreUserView这个入口类里面的东西。

也就是第一篇会比较多了 开始学习设计模式的时候又会便的很枯燥了

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343

推荐阅读更多精彩内容