這是第二次讀這本書了 有時感覺講的事真的不錯
第一次讀完什么都沒有留下 除了已經不知道哪去的源碼 只剩下詩和遠方
主要是長時間不看你 改忘得都差不多了 現在有時間在讀一遍 希望 可以把這本書的讀書筆記一直寫下去
大概一中午時間讀完了 第一章 最大的感慨就是小民最開始真的是碰到一個非常優(yōu)秀又嚴格的主管 這真是一件讓人羨慕 有難以達成的事 作為一個小場的程序員 我們只能在自己的摸索中前進了 閑話與羨慕的話不多少了 第一章的讀書筆記
為他單開一張 真的是感覺他才是本書最重要的章節(jié)
學習設計模式首先要學習的是 六大原則
設計的六大原則:
(一)單一職責原則:就一個類而言應該僅有一個引起他變化的原因
(二)開閉原則:軟件中的類應該是對擴展開放的,對修改是封閉的。
(三)里氏置換原則:引用基類的地方必須能夠透明的使用的的子類對象(感覺還沒寫過不能的)
優(yōu)點:(1) 代碼重用,減少創(chuàng)建類的成本,每個子類都擁有父類的實現方法
(2)子類與父類相似,但由于父類有區(qū)別
(3)提高代碼的可擴展性
缺點:(1)繼承是侵入性的只要繼承,就必須擁有父類所有的方法和屬性
(2)可能造成代碼冗余,靈活性降低。
(四)依賴倒置原則:高層次的模塊不依賴于低層次的模塊的實現細節(jié)
它有這么幾個關鍵點:
(1)高層模塊不能依賴低層模塊,兩者都應該依賴于其抽象
(2)抽象不依賴于細節(jié)
(3)細節(jié)依賴于抽象
(五)接口隔離原則:類之間的關系應該建立在最小的接口只上
(六)迪米特原則:至于具有直接關系的類進行交互。
下面是自己在實踐過程中的應用和思考
我們要寫的是一個自定義組合View 它包括好幾種類型
類型一

類型二

類型三

類型四

類型五

類型六

第一版
分析:我們需要建一個實體類來標識每一條的屬性
public class TimeOneVouchers {
private String time;
private String voucherNo;
private String storeName;
}
創(chuàng)建一個LinearLayout來動態(tài)添加
public class OrderStoreUserView extends LinearLayout {
// 當前狀態(tài)為所有券都被使用
public static final int SHOW_TYPE_ALL_USE = 0x0001;
// 當前狀態(tài)為有券未都被使用--(已使用)
public static final int SHOW_TYPE_NO_ALL_USE = 0x0010;
// 當前狀態(tài)為所有券未都已經失效
public static final int SHOW_TYPE_NO_ALL_FAILURE = 0x0100;
// 當前狀態(tài)為有券未都被使用--(已退款)
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 當前使用券的顯示狀態(tài) 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);
}
}
}
}
這個樣子完全不用考慮設計模式的第一版就新鮮出爐 雖然不用考慮設計模式但是也是完全可用的
但是看完第一章 感覺和小民的第一版完工很像 只是人家是被主管噠回來了 而 我們只能自己思考。
然后在現實中我們有碰到了一個很現實的問題提 接口的開發(fā)居然的app的界面 慢 你沒有辦法確認接口給你類型是什么樣子的 字段 是不是time,voucherNo,storeName這三個。這該怎么辦呢?要是個有脾氣的程序員 或者新手可能就 字段還沒給了怎么寫 ,然后就等接口處了在寫吧 這的確個解決方法。但是不應該這樣子啊,感覺有好多自定義View都可能使用的Bean他們不能重視按照所需要用的在去改源碼吧;在這里我們就應該用到依賴倒置原則 作為一個實現類時不應改 依賴于另一個實現類的細節(jié)的,我們應該讓他依賴于接口 然后我就這門改寫
寫一個接口
public interface UserVouchers {
//券的使用時間
String getTime();
// 券的使用店鋪
String getStoreName();
// 券 碼
String getVouchersNum();
}
然后把List<TimeOneVouchers> 改為List<UserVouchers > 這樣好像就可以了
改寫后的自定View類不子啊以來與原來的具體的實現Bean只依賴于 UserVouchers接口 我們只需要等接口下來不管字段是什么樣子的 只需要復寫這三個方法攤入相應的屬性就行了。
雖然加了這面幾句話就搞定了 但的確也是對面向對象的應用
這塊優(yōu)化后實際問題已經解決了,提交代碼搞定。
雖然功能已經搞定了,但是我們來看一看還有沒有其他不符合面向對象的地方繼續(xù)優(yōu)化
優(yōu)化前我們的數據結構是這樣的

根據setViewType(int type, List<UserVouchers> timeOneVouchersList)這個方法進來的參數來決定每個加載不同View的類型并賦值 明顯就不符合了單一性原則
每次技師只要修改一部分的功能還要修改這個類的代碼只明顯是和他本身的功能無關
那我們就需要修改這個類的數據結構了
根據數據結構分析
先畫了一下優(yōu)化后的UML

這樣誰不是更加清晰了呢
而且我問吧單個的功能分開是不就符合的 單一性與隔離性的原則
然后就可以開始優(yōu)化代碼 反正只要是符合6大原則 基本上都是設計模式
所以有些東西可以系統(tǒng)的想上面靠 有些不可以而已 比如說 自定義View的參數構造一般都會使用建造者模式等等 我們要是讀完整本書 即使記不住具體的設計模式也一定要記住這個第一張的6大原則 只需要 我們在做功能的基礎設計的時候網上面靠就就行了 就比如說我上上面的這種想法其實也就是一個泛指,就比如說我們在做前端 多種支付的時候也可以涉及到。
我發(fā)現這個類圖畫完只是一個預想 實際操作過程中 有余還有一寫含有公共的方法
還有少的一些參數
最終修改類圖為

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);
}
- 完成基類
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這個入口類里面的東西。
也就是第一篇會比較多了 開始學習設計模式的時候又會便的很枯燥了