一柳骄、面向?qū)ο蟮牧笤瓌t
單一職責(zé)Single Responsibility Principle突琳,縮寫SRP拓售。定義:對(duì)一個(gè)類而言晕窑,應(yīng)該僅有一個(gè)引起它變化的原因玄呛。簡(jiǎn)單來說置吓,一個(gè)類中應(yīng)該是一組相關(guān)性很高的函數(shù)菱阵。
開閉原則Open Close Principle乳蓄,縮寫OCP他爸。定義:軟件中的對(duì)象(類聂宾、模塊、函數(shù)等)應(yīng)該對(duì)于擴(kuò)展是開放的诊笤,對(duì)于修改是封裝的系谐。
里氏替換Liskov Substitution Principle,縮寫LSP讨跟。定義:所有引用基類的地方必須能透明地使用其子類的對(duì)象纪他。
依賴倒置Dependence Inversion Principle,縮寫DIP晾匠。定義:模塊間的依賴通過抽象發(fā)生茶袒,實(shí)現(xiàn)類之間不發(fā)生直接的依賴關(guān)系,其依賴關(guān)系是通過接口或抽象類產(chǎn)生的凉馆。
接口隔離原則Interface Segregation Principle薪寓,縮寫ISP。定義:客戶端不應(yīng)該依賴它不需要的接口澜共。另一種定義是:類間的依賴關(guān)系應(yīng)該建立在最小的接口上向叉。
迪米特原則Law of Demeter,縮寫LOD咳胃,也稱最少知識(shí)原則(Least Knowledge Principle)植康。定義:一個(gè)對(duì)象應(yīng)該對(duì)其他對(duì)象有最少的了解。
- 設(shè)計(jì)模式分類:
- 創(chuàng)建型:Singleton展懈、Builder销睁、Prototype、Factory Method存崖、Abstract Factory
- 結(jié)構(gòu)型:Proxy冻记、Composite、Adapter来惧、Decorator冗栗、Flyweight、Facade、Bridge
- 行為:Strategy隅居、State钠至、Chain of Responsibility、Interpreter胎源、Command棉钧、Observer、Memento涕蚤、Iterator宪卿、Template Method、Visitor万栅、Mediator
二佑钾、應(yīng)用最廣的模式——單例模式
定義:確保某一個(gè)類只有一個(gè)實(shí)例,而且自行實(shí)例化并向整個(gè)系統(tǒng)提供這個(gè)實(shí)例烦粒。
使用場(chǎng)景:比如創(chuàng)建一個(gè)對(duì)象需要消耗的資源過多休溶。
關(guān)鍵點(diǎn):構(gòu)造函數(shù)不對(duì)外開放,一般為Private撒遣;通過一個(gè)靜態(tài)方法或者枚舉返回單例類對(duì)象邮偎;確保單例類的對(duì)象有且只有一個(gè),尤其是在多線程環(huán)境下义黎;確保單例類對(duì)象在反序列化時(shí)不會(huì)重新構(gòu)建對(duì)象禾进。
簡(jiǎn)單示例:公司人員構(gòu)成,單個(gè)CEO
實(shí)現(xiàn)方式
懶漢模式:聲明一個(gè)靜態(tài)對(duì)象廉涕,并且在用戶第一次調(diào)用getInstance時(shí)進(jìn)行初始化泻云,而上述餓漢模式(CEO類)是在聲明麥太太對(duì)象時(shí)就已經(jīng)初始化。
Double Check Lock(DCL)實(shí)現(xiàn)單例:
public static Singleton getInstance() {
if (mInstance == null) {
synchronized (Singleton.class) {
if (mInstance == null) {
sInstance = new Singleton();
}
}
}
return sInstance;
}
靜態(tài)內(nèi)部類單例模式:
public static Singleton getInstance() {
return SingletonHolder.sInstance;
}
private static class SingletonHolder{
priveate static final Singleton sInstance = new Singleton();
}
枚舉單例:
public enum SingletonEnum {
INSTANCE;
public void doSomething() {
System.out.println("do sth.");
}
}
使用容器實(shí)現(xiàn)單例模式:
public class SingletonManager {
prinvate static Map<String,Object> objMap = new HashMap<String,Object>();
}
在Android源碼中:通常我們使用LayoutInflater.from(Context)來獲取LayoutInflater服務(wù)狐蜕,下面看看LayoutInflater.from(Context)的實(shí)現(xiàn)宠纯。
public static LayoutInflater from(Context context) {
LayoutInflater layoutInflater = (LayoutInflater)context.getSystemServer(Context.LAYOUT_INFLATER_SERVICE);
if(layoutInflater == null) {
throw new AssertonError("LayoutInflater not found."):
}
return layoutInflater;
}
深入理解LayoutInflater
- 小結(jié)
- 優(yōu)點(diǎn):減少內(nèi)存開支;減少系統(tǒng)的性能開銷层释;避免對(duì)資源的多重占用婆瓜;在系統(tǒng)設(shè)置全局的訪問點(diǎn),優(yōu)化和共享資源訪問贡羔。
- 缺點(diǎn):擴(kuò)展困難廉白;單例對(duì)象如果持有Context,容易引發(fā)內(nèi)存泄漏乖寒,傳遞給單例對(duì)象的Context最好是Application Context猴蹂。
三、自由擴(kuò)展你的項(xiàng)目——Builder模式
介紹:Builder模式是一步一步創(chuàng)建一個(gè)復(fù)雜對(duì)象的創(chuàng)建型模式楣嘁,它允許用戶在不知道內(nèi)部構(gòu)建細(xì)節(jié)的情況下磅轻,可以更精細(xì)地控制對(duì)象的構(gòu)造流程珍逸。該模式是為了將構(gòu)建復(fù)雜對(duì)象的過程和它的部件解耦,使得構(gòu)建過程和部件的表示隔離開來聋溜。
定義:將一個(gè)復(fù)雜對(duì)象的構(gòu)建與它的表示分享谆膳,使得同樣的構(gòu)建過程可以創(chuàng)建不同的表示。
使用場(chǎng)景:相同的方法勤婚,不同的執(zhí)行順序摹量,產(chǎn)生不同的事件結(jié)果時(shí);多個(gè)部件或零件馒胆,都可以裝配到一個(gè)對(duì)象中,但是產(chǎn)生的運(yùn)行結(jié)果又不相同時(shí)凝果;產(chǎn)品類非常復(fù)雜祝迂,或者產(chǎn)品類中的調(diào)用順序不同產(chǎn)生了不同的什么用,這個(gè)時(shí)候使用建造者模式非常合適器净;當(dāng)初始化一個(gè)對(duì)象特別復(fù)雜型雳,如參數(shù)多,且很多參數(shù)都具有默認(rèn)值時(shí)山害。
UML類圖
Product——產(chǎn)品的抽象類纠俭。
Builder——抽象Builder類,規(guī)范產(chǎn)品的組建浪慌,一般是由子類實(shí)現(xiàn)具體的邪惡v地方過程冤荆;
ConcreteBuilder——具體的Builder類;
Director——統(tǒng)一組裝的過程权纤。
簡(jiǎn)單實(shí)現(xiàn)
計(jì)算機(jī)的組裝過程
在Android源碼中
在Android源碼中钓简,最常用到的Builder模式就是AlertDialog.Builder,使用該Builder來構(gòu)建復(fù)雜的AlertDialog對(duì)象汹想。
public class AlertDialog extends Dialog implements DialogInterface{
private AlertContraller mAlert;
public void setTitle(char Sequence title) { super...;mAlert.setTitle(title);}
public static class Builder{
private final AlertController.AlertParams p;
public Builder setTitle(...) {
p.mTitle = title; return this;
}
public AlertDialog create() {
final AlertDialog dialog = new AlertDialog(p.mContext,mTheme,false);
p.apply(dialog.mAlert);
return dialog;
}
}
}
深入了解WindowManager
實(shí)戰(zhàn)
小結(jié)
優(yōu)點(diǎn):良好的封裝性外邓;建造者獨(dú)立,容易擴(kuò)展
缺點(diǎn):會(huì)產(chǎn)生多余的Builder對(duì)象以及Director對(duì)象古掏,消耗內(nèi)存损话。
四、使程序運(yùn)行更高效——原型模式
介紹:多用于創(chuàng)建復(fù)雜的或者構(gòu)造耗時(shí)的實(shí)例槽唾,在這種情況下丧枪,復(fù)制一個(gè)已經(jīng)存在的實(shí)例可使程序運(yùn)行更高效
定義:用原型實(shí)例指定創(chuàng)建對(duì)象的種類,并通過復(fù)制這些原型創(chuàng)建新的對(duì)象夏漱。
使用場(chǎng)景:1.類初始化需要消耗非常多的資源豪诲,通過原型復(fù)制避免這些消耗。2.通過new產(chǎn)生一個(gè)對(duì)象需要非常繁瑣的數(shù)據(jù)準(zhǔn)備或訪問權(quán)限挂绰,這時(shí)可以使用原型模式屎篱。3.一個(gè)對(duì)象需要提供給其他對(duì)象訪問服赎,而且各個(gè)調(diào)用者可能都需要修改其值時(shí),可以考慮使用原型模式復(fù)制多個(gè)對(duì)象供調(diào)用者使用交播,即保護(hù)性拷貝重虑。
UML類圖
Client:客戶端用戶。
Prototype:抽象類或者接口秦士,聲明具備clone能力缺厉。
ConcretePrototype:具體的原型類
簡(jiǎn)單實(shí)現(xiàn):文檔拷貝
淺拷貝和深拷貝:深拷貝對(duì)引用型的字段也采用拷貝的形式(也用上clone函數(shù)嘛)。
在Android源碼中:Intent
Intent的查找與匹配
實(shí)戰(zhàn)
小結(jié)
優(yōu)點(diǎn):原型模式是在內(nèi)存中二進(jìn)制流的拷貝隧土,要比直接new一個(gè)對(duì)象性能好很多提针,特別是要在一個(gè)循環(huán)內(nèi)產(chǎn)生大量的對(duì)象時(shí),原型模式可以更好地體現(xiàn)其優(yōu)點(diǎn)曹傀。
缺點(diǎn):減少了約束辐脖。
五、應(yīng)用最廣泛的模式——工廠方法模式
定義:定義一個(gè)用于創(chuàng)建對(duì)象的接口皆愉,讓子類決定實(shí)例化哪個(gè)類嗜价。
使用場(chǎng)景:在任何需要生成復(fù)雜對(duì)象的地方,都可以使用工廠方法模式幕庐。復(fù)雜對(duì)象適合使用工廠模式久锥,用new就可以完成創(chuàng)建的對(duì)象無需使用工廠模式。
UML類圖
Product:定義工廠方法所創(chuàng)建的對(duì)象的接口
ConcreteProduct:實(shí)現(xiàn)Product接口
Creator:聲明工廠方法异剥,該方法返回一個(gè)Product類型的對(duì)象瑟由;調(diào)用工廠方法以創(chuàng)建一個(gè)Product對(duì)象
ConcreteCreator:重定義工廠方法以返回一個(gè)ConcreteProduct實(shí)例
簡(jiǎn)單實(shí)現(xiàn):組裝汽車
public <T extends AudiCar> T createAudiCar(Class<T> clz) {
AudiCar car = null;
try {
car = (AudiCar) Class.forName(clz.getName()).newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return (T) car;
}
在Android源碼中:iterator
關(guān)于onCreate方法:對(duì)于一個(gè)app來說,入口在ActivityThread類中届吁。這是一個(gè)final類错妖,一個(gè)app對(duì)應(yīng)一個(gè)ActivityThread,當(dāng)Zygote進(jìn)程孵化出一個(gè)新的進(jìn)程后疚沐,會(huì)執(zhí)行ActivityThread的main方法暂氯,在main方法中做一些比較常規(guī)的邏輯,比如準(zhǔn)備Looper和消息隊(duì)列亮蛔,然后調(diào)用attach方法將其綁定到ActivityManagerService中痴施。
實(shí)戰(zhàn)
小結(jié)
缺點(diǎn):導(dǎo)致類結(jié)構(gòu)復(fù)雜化
六、創(chuàng)建型設(shè)計(jì)模式——抽象工廠模式
定義:為創(chuàng)建一組相關(guān)或者是相互依賴的對(duì)象提供一個(gè)接口究流,而不需要指定它們的具體類辣吃。
使用場(chǎng)景:一個(gè)對(duì)象族有相同的約束時(shí)可以使用抽象工廠模式。
UML類圖
AbstractFactory:抽象工廠角色芬探,它聲明了一組用于創(chuàng)建一種產(chǎn)品的方法神得,每一個(gè)方法對(duì)應(yīng)一種產(chǎn)品。
ConcreteFactory:具體工廠角色偷仿,它實(shí)現(xiàn)了在抽象工廠中定義的創(chuàng)建產(chǎn)品的方法哩簿,生成一組具體產(chǎn)品宵蕉,這些產(chǎn)品構(gòu)成了一個(gè)產(chǎn)品種類,每一個(gè)產(chǎn)品都位于某個(gè)產(chǎn)品等級(jí)結(jié)構(gòu)中节榜。
AbstractProduct:抽象產(chǎn)品種類羡玛,它為每種產(chǎn)品聲明接口。
ConcreteProduct:具體產(chǎn)品角色宗苍,它定義具體工廠生產(chǎn)的具體產(chǎn)品對(duì)象稼稿,實(shí)現(xiàn)抽象產(chǎn)品接口中聲明的業(yè)務(wù)方法。
簡(jiǎn)單實(shí)現(xiàn):汽車工廠生產(chǎn)部件
在Android源碼中:Android底層對(duì)MediaPlayer的創(chuàng)建讳窟。
在Android開發(fā)中的應(yīng)用:主題樹
小結(jié)
優(yōu)點(diǎn):分離接口與實(shí)現(xiàn)
缺點(diǎn):類文件的爆炸性增加让歼;不太容易擴(kuò)展新的產(chǎn)品類
七、時(shí)勢(shì)造英雄——策略模式
定義:策略模式定義了一系列的算法挪钓,并將每一個(gè)算法封裝起來是越,而且使它們還可以互相替換。
使用場(chǎng)景
針對(duì)同一類型問題的多種處理方法碌上,僅僅是具體行為有差別時(shí)
需要安全地封裝多種同一類型的操作時(shí)
出現(xiàn)同一抽象類有多個(gè)子類,而又需要使用if-else或者switch-case來選擇具體子類時(shí)
UML類圖
Context——用來操作策略的上下文環(huán)境
Stragety——策略的抽象
ConcreteStragetyA浦徊、ConcreteStragetyB——具體的策略實(shí)現(xiàn)
簡(jiǎn)單實(shí)現(xiàn):公共交通費(fèi)用計(jì)算
在Android源碼中:時(shí)間插值器
深入屬性動(dòng)畫
實(shí)戰(zhàn)
小結(jié)
優(yōu)點(diǎn):結(jié)構(gòu)清晰明了馏予、使用簡(jiǎn)單直觀;耦合度相對(duì)而言較低盔性,擴(kuò)展方便霞丧;操作封裝也更為徹底、數(shù)據(jù)更為安全
缺點(diǎn):隨著策略的增加冕香,子類也會(huì)變得繁多蛹尝。
八、隨遇而安——狀態(tài)模式
定義:當(dāng)一個(gè)對(duì)象的內(nèi)在狀態(tài)改變時(shí)允許改變其行為悉尾,這個(gè)對(duì)象看起來像是改變了其類突那。
使用場(chǎng)景:一個(gè)對(duì)象的行為取決于它的狀態(tài),并且它必須在運(yùn)行時(shí)根據(jù)狀態(tài)改變它的行為构眯;代碼中包含大量與對(duì)象狀態(tài)有關(guān)的條件語句愕难,例如,一個(gè)操作中含有龐大的多分支語句惫霸,且這些分支依賴于該對(duì)象的狀態(tài)猫缭;
UML類圖
Context:環(huán)境類,定義客戶感興趣的接口壹店,維護(hù)一個(gè)State子類的實(shí)例猜丹,這個(gè)實(shí)例定義了對(duì)象的當(dāng)前狀態(tài)。
State:抽象狀態(tài)類或者狀態(tài)接口硅卢,定義一個(gè)或者一組接口射窒,表示該狀態(tài)下的行為藏杖。
ConcreteStateA、ConcreteStateB:具體狀態(tài)類轮洋,每一個(gè)具體的狀態(tài)類實(shí)現(xiàn)抽象State中定義的接口制市,從而達(dá)到不同狀態(tài)下的不同行為。
簡(jiǎn)單示例:電視遙控器
狀態(tài)模式:WIFI管理
實(shí)戰(zhàn):登錄系統(tǒng)
小結(jié)
優(yōu)點(diǎn):State模式將所有與一個(gè)特定的狀態(tài)相關(guān)的行為都放入一個(gè)狀態(tài)對(duì)象中弊予,它提供了一個(gè)更好的方法來組織與特定狀態(tài)相關(guān)的代碼,將煩瑣的狀態(tài)判斷轉(zhuǎn)換成結(jié)構(gòu)清晰的狀態(tài)類族误褪,在避免代碼膨脹的同時(shí)也保證了可擴(kuò)展性與可維護(hù)性碾褂。
缺點(diǎn):增加系統(tǒng)類和對(duì)象的個(gè)數(shù)兽间。
九、使編程更有靈活性——責(zé)任鏈模式
定義:使多個(gè)對(duì)象都有機(jī)會(huì)處理請(qǐng)求正塌,從而避免了請(qǐng)求的發(fā)送者和接收者之間的耦合關(guān)系嘀略。將這些對(duì)象連成一條鏈,并沿著這條鏈傳遞該請(qǐng)求乓诽,直到有對(duì)象處理它為止帜羊。
使用場(chǎng)景:多個(gè)對(duì)象可以處理同一請(qǐng)求,但具體由哪個(gè)對(duì)象處理則在運(yùn)行時(shí)動(dòng)態(tài)決定鸠天;在請(qǐng)求處理者不明確的情況下向多個(gè)對(duì)象中的一個(gè)提交一個(gè)請(qǐng)求讼育;需要?jiǎng)討B(tài)指定一組對(duì)象處理請(qǐng)求。
UML類圖
Handler:抽象處理者角色稠集,聲明一個(gè)請(qǐng)求處理的方法奶段,并在其中保持一個(gè)對(duì)下一個(gè)處理節(jié)點(diǎn)Handler對(duì)象的引用。
ConcreteHandler:具體處理者角色剥纷,對(duì)請(qǐng)求進(jìn)行處理痹籍,如果不能處理則將該請(qǐng)求轉(zhuǎn)發(fā)給下一個(gè)節(jié)點(diǎn)上的處理對(duì)象。
簡(jiǎn)單實(shí)現(xiàn):報(bào)銷費(fèi)用
在Android源碼中:ViewGroup中將事件派發(fā)到子View
實(shí)戰(zhàn)
小結(jié)
優(yōu)點(diǎn):對(duì)請(qǐng)求者和處理者關(guān)系解耦筷畦,提高代碼的靈活性词裤。
缺點(diǎn):對(duì)鏈中請(qǐng)求處理者的遍歷太多,會(huì)影響性能鳖宾。
十吼砂、化繁為簡(jiǎn)的翻譯機(jī)——解釋器模式
介紹:Interpreter Pattern是一種用得比較少的行為型模式,其提供了一種解釋語言的語法或表達(dá)式的方式周偎,該模式定義了一個(gè)表達(dá)式接口澳眷,通過該接口解釋一個(gè)特定的上下文钳踊。
定義: 給定一個(gè)語言,定義它的方法的一種表示祭埂,并定義一個(gè)解釋器,該解釋器使用該表示來解釋語言中的句子航罗。
使用場(chǎng)景:如果某個(gè)簡(jiǎn)單的語言需要解釋執(zhí)行而且可以將該語言中的語句表示為一個(gè)抽象語法樹時(shí)柏锄,可以考慮使用解釋器模式缭嫡;在某些特定的領(lǐng)域出現(xiàn)不斷重復(fù)的問題時(shí)妇蛀,可以將該領(lǐng)域的問題轉(zhuǎn)化為一種語法規(guī)則下的語句,然后構(gòu)建解釋器來解釋該語句纵诞。
UML類圖
AbstractExpression:抽象表達(dá)式
TerminalExpression:終結(jié)符表達(dá)式
NonterminalExpression:非終結(jié)符表達(dá)式
Context:上下文環(huán)境類
Client:客戶類
簡(jiǎn)單實(shí)現(xiàn):數(shù)學(xué)運(yùn)算
在Android源碼中:PackageParser
關(guān)于PackageManagerService
小結(jié)
優(yōu)點(diǎn):靈活的擴(kuò)展性
缺點(diǎn):生成大量的類,對(duì)于過于復(fù)雜的方法纸俭,構(gòu)建其抽象語法樹會(huì)顯得異常煩瑣揍很。
十一、讓程序暢通執(zhí)行——命令模式
定義:將一個(gè)請(qǐng)求封裝成一個(gè)對(duì)象,從而讓用戶使用不同的請(qǐng)求把客戶端參數(shù)化北救;對(duì)請(qǐng)求排隊(duì)或者記錄請(qǐng)求日志,以及支持可撤銷的操作攘宙。
使用場(chǎng)景:需要抽象出待執(zhí)行的動(dòng)作,然后以參數(shù)的形式提供出來——類似于過程設(shè)計(jì)中的回調(diào)機(jī)制铺韧,而命令模式正是回調(diào)機(jī)制的一個(gè)面向?qū)ο蟮奶娲贰?br>
在不同的時(shí)刻指定哈打、排列和執(zhí)行請(qǐng)求。一個(gè)命令對(duì)象可以有與初始請(qǐng)求無關(guān)的生存期罢维。
需要支持取消操作。
支持修改日志功能吓肋,這樣當(dāng)系統(tǒng)崩潰時(shí),這些修改可以被重做一遍均蜜。
需要支持事務(wù)操作。
UML類圖
Receiver:接收者角色
Command:命令角色
ConcreteCommand:具體命令角色
Invoker:請(qǐng)求者角色
Client:客戶端角色
簡(jiǎn)單實(shí)現(xiàn):俄羅斯方塊
在Android源碼中:在Android事件機(jī)制中底層連加對(duì)事件的轉(zhuǎn)發(fā)處理,Android的每一種事件在屏幕上產(chǎn)生后都會(huì)經(jīng)由底層邏輯將其轉(zhuǎn)換為一個(gè)NotifyArgs對(duì)象椎麦。
Android事件輸入系統(tǒng)介紹
命令模式實(shí)戰(zhàn)
十二段化、解決解耦的鑰匙——觀察者模式
介紹:觀察者模式是一個(gè)使用率非常高的模式,它最常用的地方是GUI系統(tǒng)佃延、訂閱——發(fā)布系統(tǒng)。
定義:定義對(duì)象間一種一對(duì)多的依賴關(guān)系坐桩,使得每當(dāng)一個(gè)對(duì)象改變狀態(tài)膘螟,則所有依賴于它的對(duì)象都會(huì)得到通知并被自動(dòng)更新。
使用場(chǎng)景
關(guān)聯(lián)行為場(chǎng)景内斯,需要注意的是,關(guān)聯(lián)行為是可拆分的真朗,而不是“組合”關(guān)系此疹;
事件多級(jí)觸發(fā)場(chǎng)景;
跨系統(tǒng)的消息交換場(chǎng)景蜜猾,如消息隊(duì)列秀菱、事件總線的處理機(jī)制。
UML類圖
Subject:抽象主題題
ConcreteSubject:具體主題
Observer:抽象觀察者
ConcreteObserver:具體的觀察者
簡(jiǎn)單實(shí)現(xiàn):發(fā)布——訂閱過程
public class ObserverTest {
public static class Coder implements Observer {
public String name;
public Coder(String name) {
this.name = name;
}
@Override
public void update(Observable o,Object args) {
System.out.println("Hi, " + name + ",It's update: " + args);
}
@Override
public String toString() {
return "Coder: " + name;
}
}
public static class DevTechFrontier extends Observable {
public void postNewPublication(String content) {
setChanged();
notifyObservers(content);
}
}
public static void main(String[] args) {
DevTechFrontier devTechFrontier = new DevTechFrontier();
Coder coder1 = new Coder("coder1");
Coder coder2 = new Coder("coder2");
Coder coder3 = new Coder("coder3");
devTechFrontier.addObserver(coder1);
devTechFrontier.addObserver(coder2);
devTechFrontier.addObserver(coder3);
devTechFrontier.postNewPublication("hahahahahahhhhahahahha");
}
}
Observer和Observable是JDK中內(nèi)置類型蹭睡,Observer是抽象的觀察者角色,Coder是具體的觀察者角色祟昭;Observable是抽象的被觀察者角色,DevTechFrontier是具體的被觀察者角色疾忍。當(dāng)DevTechFrontier有更新時(shí)歧沪,會(huì)遍歷所有觀察者(這里是Coder)裕菠,然后給這些觀察者發(fā)布一個(gè)更新的消息平委,即調(diào)用Coder的update方法岗照,這樣就達(dá)到了一對(duì)多的通知功能熙宇。在這個(gè)過程中,通知系統(tǒng)都是依賴Observer和Observable這些抽象類诞吱,因此阿趁,對(duì)于Coder和DevTechFrontier完全沒有耦合蘑辑,保證了訂閱系統(tǒng)的靈活性副砍,可擴(kuò)展性谨垃。
在Android源碼中:ListView的Adapter
觀察者模式的深入拓展: BroadcastReceiver
實(shí)戰(zhàn)
小結(jié)
優(yōu)點(diǎn):觀察者和被觀察者之間是抽象耦合撼短,應(yīng)對(duì)業(yè)務(wù)變化;增強(qiáng)系統(tǒng)靈活性膀捷、可擴(kuò)展性
缺點(diǎn):執(zhí)行效率低
十三迈嘹、編程中的“后悔藥”——備忘錄模式
介紹:是一種行為模式,該模式用于保存對(duì)象當(dāng)前狀態(tài)全庸,并且在之后可以再次恢復(fù)到此狀態(tài)秀仲。
定義:在不破壞封閉的前提下,捕獲一個(gè)對(duì)象的內(nèi)部狀態(tài)壶笼,并在該對(duì)象之外保存這個(gè)狀態(tài)神僵,這樣,以后就可將該對(duì)象恢復(fù)到原先保存的狀態(tài)覆劈。
使用場(chǎng)景
需要保存一個(gè)對(duì)象在某一個(gè)時(shí)刻的狀態(tài)或部分狀態(tài)
如果用一個(gè)接口來讓其他對(duì)象得到這些狀態(tài)保礼,將會(huì)暴露對(duì)象的實(shí)現(xiàn)細(xì)節(jié)并破壞對(duì)象的封裝性,一個(gè)對(duì)象不希望外界直接訪問其內(nèi)部狀態(tài)责语,通過中間對(duì)象可以間接訪問其內(nèi)部狀態(tài)炮障。
UML類圖
Originator:負(fù)責(zé)創(chuàng)建一個(gè)備忘錄,可以記錄坤候、恢復(fù)自身的內(nèi)部狀態(tài)胁赢。
Memento:備忘錄角色,用于存儲(chǔ)Originator的內(nèi)部狀態(tài)白筹,并且可以子上Originator以外的對(duì)象訪問Memento智末。
Caretaker:負(fù)責(zé)存儲(chǔ)備忘錄,不能對(duì)備忘錄的內(nèi)容進(jìn)行操作和訪問徒河,只能將備忘錄傳遞給其他對(duì)象
簡(jiǎn)單示例:游戲存檔
在Android源碼中: Activity中的狀態(tài)保存系馆。
深度拓展
實(shí)戰(zhàn)
小結(jié)
優(yōu)點(diǎn):給用戶提供了一種可以恢復(fù)狀態(tài)的機(jī)制,可以使用戶能夠比較方便地回到某個(gè)歷史的狀態(tài)虚青;實(shí)現(xiàn)了信息的封裝它呀,使得用戶不需要關(guān)心狀態(tài)的保存細(xì)節(jié)。
缺點(diǎn):消耗資源
十四棒厘、解決問題的“第三者”——迭代器模式
定義:提供一種方法順序訪問一個(gè)容器對(duì)象中的各個(gè)元素纵穿,而又不需要暴露該對(duì)象的內(nèi)部表示。
使用場(chǎng)景:遍歷一個(gè)容器對(duì)象時(shí)
UML類圖
Iterator:迭代器接口
Concrete Iterator:具體迭代器類
Aggregate:容器接口
Concrete Aggregate:具體容器類
Client:客戶類
簡(jiǎn)單實(shí)現(xiàn):員工遍歷
在Android源碼中:數(shù)據(jù)庫查詢使用的Cursor
小結(jié)
優(yōu)點(diǎn):支持以不同的方式去遍歷一個(gè)容器對(duì)象
缺點(diǎn):類文件的增加
十五奢人、抓住問題核心——模板方法模式
定義:定義一個(gè)操作中的算法的框架谓媒,而將一些步驟延遲到子類中,使得子類可以不改變一個(gè)算法的結(jié)構(gòu)即可重定義該算法的某些特定步驟何乎。
使用場(chǎng)景
多個(gè)子類有公有的方法句惯,并且邏輯基本相同時(shí)土辩;
重要、復(fù)雜的算法抢野,可以把核心算法設(shè)計(jì)為模板方法拷淘,周邊的相關(guān)細(xì)節(jié)功能則由各個(gè)子類實(shí)現(xiàn)
重構(gòu)時(shí),模板方法模式是一個(gè)經(jīng)常使用的模式指孤,把相同的代碼抽取到父類中启涯,然后通過鉤子函數(shù)約束其行為
UML類圖
AbsTemplate:抽象類,定義了一套算法框架
ConcreteImplA:具體實(shí)現(xiàn)類A
ConcreteImplB:具體實(shí)現(xiàn)類B
簡(jiǎn)單示例:碼農(nóng)和軍事計(jì)算機(jī)開機(jī)
在Android源碼中:AsyncTask
嘗試拓展:Activity的生命周期函數(shù)
實(shí)戰(zhàn)
小結(jié)
優(yōu)點(diǎn):封裝不變部分恃轩,擴(kuò)展可變部分结洼;提取公共部分代碼,便于維護(hù)
缺點(diǎn):代碼閱讀難度提高
十六叉跛、訪問者模式
介紹:是一種將數(shù)據(jù)操作與數(shù)據(jù)結(jié)構(gòu)分享的設(shè)計(jì)模式松忍,是23種最復(fù)雜的一個(gè),但使用頻率并不高筷厘。
定義:封裝一些作用于某種數(shù)據(jù)結(jié)構(gòu)中的各元素的操作鸣峭,它可以在不改變這個(gè)數(shù)據(jù)結(jié)構(gòu)的前提下定義什么用于這些元素的新的操作。
使用場(chǎng)景
對(duì)象結(jié)構(gòu)比較穩(wěn)定敞掘,但經(jīng)常需要在此對(duì)象結(jié)構(gòu)上定義新的操作
需要對(duì)一個(gè)對(duì)象結(jié)構(gòu)中的對(duì)象進(jìn)行很多不同的并且不相關(guān)的操作叽掘,而需要避免這些操作“污染”這些對(duì)象的類,也不希望在增加新操作時(shí)修改這些類玖雁。
UML類圖
Visitor:接口或者抽象類更扁,它定義了對(duì)每一個(gè)元素訪問的行為
ConcreteVisitor:具體的訪問者,它需要給出對(duì)每一個(gè)元素類訪問時(shí)所產(chǎn)生的具體行為
Element:元素接口或者抽象類赫冬,它定義了一個(gè)接收訪問者(accept)的方法浓镜,其意義是指每一個(gè)元素都要可以被訪問者訪問
ElementA、ElementB:具體的元素類劲厌,它提供接受訪問方法的具體實(shí)現(xiàn)膛薛,而這個(gè)具體的實(shí)現(xiàn),通常情況下是使用訪問者提供的訪問該元素類的方法
ObjectStructure:定義當(dāng)中所提到的對(duì)象結(jié)構(gòu)补鼻,對(duì)象結(jié)構(gòu)是一個(gè)抽象表述哄啄,它內(nèi)部管理了元素集合,并且可以迭代這些元素供訪問者訪問
簡(jiǎn)單示例:老板风范、CTO對(duì)員工的訪問
在Android源碼中:編譯時(shí)注解
實(shí)戰(zhàn):實(shí)現(xiàn)APT
小結(jié)
優(yōu)點(diǎn):各角色職責(zé)分享咨跌,符合單一職責(zé)原則;具體優(yōu)秀的擴(kuò)展性硼婿;使得數(shù)據(jù)結(jié)構(gòu)和什么用于結(jié)構(gòu)上的操作解耦锌半,使得操作集合可以獨(dú)立變化;靈活性
缺點(diǎn):具體元素對(duì)訪問者公布細(xì)節(jié)寇漫,違反迪米特原則刊殉;具體元素變更時(shí)導(dǎo)致修改成本大殉摔;違反了依賴倒置原則,為了達(dá)到“區(qū)別對(duì)待”而依賴了具體類记焊,沒有依賴抽象
十七逸月、“和事佬”——中介者模式
定義:中介者模式包裝了一系列對(duì)象相互作用的方式,使得這些對(duì)象不必相互明顯作用
使用場(chǎng)景:當(dāng)對(duì)象之間的交互操作很多且每個(gè)對(duì)象的行為操作都依賴彼此時(shí)遍膜,為防止在修改一個(gè)對(duì)象的行為時(shí)彻采,同時(shí)涉及修改很多其他對(duì)象的行為。
UML類圖
Mediator:抽象中介者角色捌归,定義了同事對(duì)象到中介者對(duì)象的接口,一般以抽象類的方式實(shí)現(xiàn)
ConcreteMediator:具體中介者角色岭粤,繼承于抽象中介者惜索,實(shí)現(xiàn)了父類定義的方法,它從具體的同事對(duì)象接收消息剃浇,向具體同事對(duì)象發(fā)出命令
Colleague:抽象同事類角色巾兆,定義了中介者對(duì)象的接口,它只知道中介者而不知道其他的同事對(duì)象
ConcreteColleagueA/B:具體同事類角色虎囚,繼承于抽象同事類角塑,每個(gè)具體同事類都知道本身在小范圍內(nèi)的TF喲里,而不知道它在大范圍內(nèi)的目的
簡(jiǎn)單實(shí)現(xiàn):計(jì)算機(jī)的組成
在Android源碼中: Keyguard鎖屏
實(shí)戰(zhàn)
小結(jié)
優(yōu)點(diǎn):如果類間的依賴關(guān)系如網(wǎng)關(guān)般復(fù)雜淘讥,對(duì)依賴關(guān)系進(jìn)行解耦使邏輯結(jié)構(gòu)清晰
缺點(diǎn):如果依賴關(guān)系不復(fù)雜圃伶,使用中介者模式反而使得原本不復(fù)雜的邏輯結(jié)構(gòu)變得復(fù)雜
十八、編程好幫手——代理模式
定義:為其他對(duì)象提供一種代理以控制對(duì)這個(gè)對(duì)象的訪問
使用場(chǎng)景:當(dāng)無法或不想直接訪問某個(gè)對(duì)象或訪問某個(gè)對(duì)象存在困難時(shí)可以通過一個(gè)代理對(duì)象來間接訪問蒲列,為了保證客戶端使用的透明性窒朋,委托對(duì)象與代理對(duì)象需要實(shí)現(xiàn)相同的接口
UML類圖
Subject:抽象主題類
RealSubject:真實(shí)主題類
ProxySubject:代理類
Client:客戶類
簡(jiǎn)單實(shí)現(xiàn):代理律師
在Android源碼中:ActivityManagerProxy代理類
Android中的Binder跨進(jìn)程通信機(jī)制與AIDL
實(shí)戰(zhàn) :對(duì)于不同布局通知選擇
小結(jié)
缺點(diǎn):類的增加
十九、物以類聚——組合模式
介紹:Composite Pattern也稱為部分整體模式(Part-Whole Pattern)蝗岖,結(jié)構(gòu)型設(shè)計(jì)模式侥猩,它將一組相似的對(duì)象看作一個(gè)對(duì)象處理,并根據(jù)一個(gè)樹狀結(jié)構(gòu)來組合對(duì)象抵赢,然后提供一個(gè)統(tǒng)一的方法去訪問相應(yīng)的對(duì)象欺劳,以此忽略掉對(duì)象與對(duì)象集合之間的差別。
定義:將對(duì)象組合成樹形結(jié)構(gòu)以表示“部分——整體”的層次結(jié)構(gòu)铅鲤,使得用戶對(duì)單個(gè)對(duì)象和組合對(duì)象的使用具有一致性划提。
使用場(chǎng)景
表示對(duì)象的部分——整體層次結(jié)構(gòu)時(shí)。
從一個(gè)整體中能夠獨(dú)立出部分模塊或功能的場(chǎng)景彩匕。
UML類圖
Component:抽象根節(jié)點(diǎn)腔剂,為組合中的對(duì)象聲明接口
Composite:定義有子節(jié)點(diǎn)的那些枝干節(jié)點(diǎn)的行為,存儲(chǔ)子節(jié)點(diǎn)驼仪,在Component接口中實(shí)現(xiàn)與子節(jié)點(diǎn)有關(guān)的操作
Leaf:在組合中表示葉子節(jié)點(diǎn)對(duì)象掸犬,葉子節(jié)點(diǎn)沒有子節(jié)點(diǎn)袜漩,在組合中定義節(jié)點(diǎn)對(duì)象的行為
Client:通過Component接口操縱組合節(jié)點(diǎn)的對(duì)象
簡(jiǎn)單實(shí)現(xiàn):文件和文件夾
在Android源碼中:View與ViewGroup的嵌套組合
為什么ViewGroup有容器的功能
小結(jié)
優(yōu)點(diǎn):可以清楚地定義分層次的復(fù)雜對(duì)象肢簿,表示對(duì)象的全部或部分層次冤灾,它讓高層模塊忽略了層次的差異,方便對(duì)整個(gè)層次結(jié)構(gòu)進(jìn)行控制堕担;高層模塊可以一致地使用一個(gè)組合結(jié)構(gòu)或其中單個(gè)對(duì)象介褥,不必關(guān)心處理的是單個(gè)對(duì)象還是整個(gè)組合結(jié)構(gòu)座掘,簡(jiǎn)化了高層模塊的代碼;增加新的枝干構(gòu)件和葉子構(gòu)件都很方便柔滔,無須對(duì)現(xiàn)有類庫進(jìn)行任何修改溢陪,符合“開閉原則”;為樹形結(jié)構(gòu)的面向?qū)ο髮?shí)現(xiàn)提供了一種靈活的解決方案睛廊,通過路子對(duì)象和枝干對(duì)象的遞歸組合形真,可以形成復(fù)雜的樹形結(jié)構(gòu),但對(duì)樹形結(jié)構(gòu)的控制卻非常簡(jiǎn)單超全。
缺點(diǎn):在新增構(gòu)件時(shí)不好對(duì)枝干中的構(gòu)件類型進(jìn)行限制咆霜,不能依賴類型系統(tǒng)來施加這些約束,因?yàn)樵诖蠖鄶?shù)情況下嘶朱,它們都來自于相同的抽象層蛾坯,此時(shí),必須進(jìn)行類型檢查來實(shí)現(xiàn)疏遏,這個(gè)實(shí)現(xiàn)過程較為復(fù)雜脉课。
二十、得心應(yīng)手的“粘合劑”——適配器模式
定義:適配器模式把一個(gè)類的接口變換成客戶端所期待的另一種接口财异,從而使原本因接口不匹配而無法在一起工作的兩個(gè)類能夠在一起工作下翎。
使用場(chǎng)景
系統(tǒng)需要使用現(xiàn)有的類,而此類的接口不符合系統(tǒng)的需要宝当,即接口不兼容
想要建立一個(gè)可以重復(fù)使用的類视事,用于一些彼此之間沒有太大關(guān)聯(lián)的一些類,包括一些可能在將來引進(jìn)的類一起工作
需要一個(gè)統(tǒng)一的輸出接口庆揩,而輸入端的類型不可預(yù)知
UML類圖
Target:目標(biāo)角色
Adaptee:現(xiàn)在需要適配的接口
Adapter:適配器角色俐东,
簡(jiǎn)單示例:220V電壓轉(zhuǎn)換為5V
在Android源碼中: ListView的Adapter
嘗試拓展
實(shí)戰(zhàn)演示
小結(jié)
優(yōu)點(diǎn):更好的復(fù)用性、更好的擴(kuò)展性
缺點(diǎn):過多使用適配器订晌,會(huì)讓系統(tǒng)非常零亂虏辫,不易整體把握
二十一、裝飾模式
介紹:其使用一種對(duì)客戶端透明的方式來動(dòng)態(tài)地?cái)U(kuò)展對(duì)象的功能锈拨,同時(shí)它也是繼承關(guān)系的一種替代方案之一砌庄。
定義:動(dòng)態(tài)地給一個(gè)對(duì)象添加一些額外的職責(zé)。就增加功能來說,裝飾模式生成子類更為靈活娄昆。
使用場(chǎng)景:需要透明且動(dòng)態(tài)地?cái)U(kuò)展類的功能時(shí)
UML類圖
Component:抽象組件
ConcreteComponent:組件具體實(shí)現(xiàn)類
Decorator:抽象裝飾者
ConcreteDecoratorA:裝飾者具體實(shí)現(xiàn)類
簡(jiǎn)單實(shí)現(xiàn):穿衣服
在Android源碼中:Context類
Context與ContextImpl
模式實(shí)戰(zhàn)
小結(jié)
二十二佩微、對(duì)象共享,避免創(chuàng)建多對(duì)象——享元模式
定義: 使用共享對(duì)象可有效地支持大師的細(xì)粒度的對(duì)象
使用場(chǎng)景
系統(tǒng)中存在大量的相似對(duì)象
細(xì)粒度的對(duì)象都具備較接近的外部狀態(tài)萌焰,而且內(nèi)部狀態(tài)與環(huán)境無關(guān)哺眯,也就是說對(duì)象沒有特定身份
需要緩沖池的場(chǎng)景
UML類圖
Flyweight:享元對(duì)象抽象基類或者接口
ConcreateFlyweight:具體的享元對(duì)象
FlyweightFactory:享元工廠
簡(jiǎn)單示例:買票軟件
在Android源碼中:Handler、Looper
深度拓展
小結(jié)
優(yōu)點(diǎn):大幅度地降低內(nèi)存中對(duì)象的數(shù)量
缺點(diǎn):使得系統(tǒng)更加復(fù)雜扒俯;將享元對(duì)象的狀態(tài)外部化奶卓,而讀取外部狀態(tài)使得運(yùn)行時(shí)間稍微變長
二十三、統(tǒng)一編程接口——外觀模式
介紹:Facade在第三方SDK中應(yīng)用廣泛撼玄,通過一個(gè)外觀類使得整個(gè)系統(tǒng)的接口只有一個(gè)統(tǒng)一的高層接口夺姑。
定義:要求一個(gè)子系統(tǒng)的外部與其內(nèi)部的通信必須通過一個(gè)統(tǒng)一的對(duì)象進(jìn)行。Facade模式提供一個(gè)高層次的接口掌猛,使得子系統(tǒng)更易于使用
使用場(chǎng)景
為一個(gè)復(fù)雜子系統(tǒng)提供一個(gè)簡(jiǎn)單接口
當(dāng)你需要構(gòu)建一個(gè)層次結(jié)構(gòu)的子系統(tǒng)時(shí)瑟幕,使用Facade模式定義子系統(tǒng)中每層的入口點(diǎn)。如果子系統(tǒng)之間是相互依賴的留潦,你可以讓它們僅通過Facade接口進(jìn)行通信,從而簡(jiǎn)化了它們之間的依賴關(guān)系
UML類圖
Facade:系統(tǒng)對(duì)外的統(tǒng)一接口辣往,系統(tǒng)內(nèi)部系統(tǒng)地工作
SystemA兔院、SystemB、SystemC:子系統(tǒng)接口
簡(jiǎn)單示例:手機(jī)
在Android源碼中:ContextImpl
深度拓展
實(shí)戰(zhàn)
小結(jié)
優(yōu)點(diǎn):對(duì)客戶程序隱藏子系統(tǒng)細(xì)節(jié)站削,因而減少了客戶對(duì)于子系統(tǒng)的耦合坊萝,能夠擁抱變化;外觀類對(duì)子系統(tǒng)的接口封裝许起,使得系統(tǒng)更易于使用
缺點(diǎn):外觀類接口膨脹十偶;外觀類沒有遵循開閉原則,當(dāng)業(yè)務(wù)出現(xiàn)變更時(shí)园细,可能需要直接修改外觀類
二十四惦积、連接兩地的交通樞紐——橋接模式
定義:將抽象部分與實(shí)現(xiàn)部分分離,使它們都可以獨(dú)立地進(jìn)行變化
使用場(chǎng)景
任何多維度變化類或者說多個(gè)樹狀類之間的耦合都可以使用橋接模式來實(shí)現(xiàn)解耦
如果一個(gè)系統(tǒng)需要在構(gòu)件的抽象化角色和具體化角色之間增加更多的靈活性猛频,避免在兩個(gè)層次之間建立靜態(tài)的繼承聯(lián)系狮崩,可能通過橋接模式使它們?cè)诔橄髮咏⒁粋€(gè)關(guān)聯(lián)關(guān)系
對(duì)于那些不希望使用繼承或因?yàn)槎鄬哟卫^承導(dǎo)致系統(tǒng)類的個(gè)數(shù)急劇增加的系統(tǒng),也可以考慮使用橋接模式
一個(gè)類存在兩個(gè)獨(dú)立變化的維度鹿寻,且這兩個(gè)維度都需要進(jìn)行擴(kuò)展
UML類圖
Abstraction:抽象部分
RefinedAbstraction:優(yōu)化的抽象部分
Implementor:實(shí)現(xiàn)部分
ConcreteImplementorA/ConcreteImplementorB:實(shí)現(xiàn)部分的具體實(shí)現(xiàn)
Client:客戶類
簡(jiǎn)單實(shí)現(xiàn):咖啡大小杯是否加糖
在Android源碼中:Window與WindowManager
關(guān)于WindowManagerService
實(shí)戰(zhàn)
小結(jié)
優(yōu)點(diǎn):分離抽象與實(shí)現(xiàn)睦柴、靈活的擴(kuò)展、對(duì)客戶來說透明的實(shí)現(xiàn)
缺點(diǎn):不容易設(shè)計(jì)
二十五毡熏、MVC的介紹與實(shí)戰(zhàn)
MVC在Android中的實(shí)現(xiàn)
ListView與Adapter
圖片顯示實(shí)例:
public class Model {
private final Handler mHandler = new Handler();
private OnStateChangeListener mListener;
private Bitmap mBitmap;
private Context mContext;
public interface OnStateChangeListener {
void onStateChanged(Bitmap image);
}
public Model(Context context) {
mContext = context;
mBitmap = BitmapFactory.decodeResource(context.getResources(),R.mipmap.ic_launcher);
}
public void setOnStateChangeListener(OnStateChangeListener listener) {
mListener = listener;
}
public void loadImage() {
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(3000);
mBitmap = BitmapFactory.decodeResource(mContext.getResources(),R.mipmap.ic_launcher);
if (null != mListener)
mHandler.post(new Runnable() {
@Override
public void run() {
mListener.onStateChanged(mBitmap);
}
});
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
public void clear() {
mBitmap = null;
if (null != mListener)
mHandler.post(new Runnable() {
@Override
public void run() {
mListener.onStateChanged(null);
}
});
}
public Bitmap getBitmap() {
return mBitmap;
}
}
public class MainActivity extends AppCompatActivity implements Model.OnStateChangeListener{
private ImageView mIVImage;
private Model mModel;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mModel = new Model(this);
mModel.setOnStateChangeListener(this);
mIVImage = (ImageView) findViewById(R.id.main_image_iv);
mIVImage.setImageBitmap(mModel.getBitmap());
}
public void onClick(View view) {
switch (view.getId()) {
case R.id.main_load_btn:
mModel.loadImage();
break;
case R.id.main_clear_btn:
mModel.clear();
break;
}
}
@Override
public void onStateChanged(Bitmap image) {
mIVImage.setImageBitmap(image);
}
}
二十六坦敌、MVP應(yīng)用架構(gòu)模式
MVP模式的三個(gè)角色
Presenter——交互中間人:主要作為溝通View和Model的橋梁,它從Model層檢索數(shù)據(jù)后,返回給View層狱窘,使得View和Model之間沒有耦合杜顺,也將業(yè)務(wù)邏輯從View角色上抽離出來。
View——用戶界面:通常指Activity训柴、Fragment或者某個(gè)View控件哑舒,它含有一個(gè)Presenter成員變量。通常View需要實(shí)現(xiàn)一個(gè)邏輯接口幻馁,將View上的操作通過會(huì)轉(zhuǎn)交給Presenter進(jìn)行實(shí)現(xiàn)洗鸵,最后,Presenter調(diào)用View邏輯接口將結(jié)果返回給View元素仗嗦。
Model——數(shù)據(jù)的存缺毂酢:對(duì)于一個(gè)結(jié)構(gòu)化的App來說,Model角色主要是提供數(shù)據(jù)的存取功能稀拐。Presenter需要通過Model層存儲(chǔ)火邓、獲取數(shù)據(jù),Model就像一個(gè)數(shù)據(jù)倉庫德撬。更直白地說铲咨,Model是封裝了數(shù)據(jù)庫DAO或者網(wǎng)絡(luò)獲取數(shù)據(jù)的角色,或者兩種數(shù)據(jù)獲取方式的集合蜓洪。
NavigationView中的MVP模式:NavigationView實(shí)際上是一個(gè)FrameLayout纤勒,在這個(gè)FrameLayout中又包含了一個(gè)RecyclerView。如果用戶設(shè)置了Header布局隆檀,那么NavigationView就把這個(gè)Header作為RecyclerView的第一個(gè)Item View摇天,在Header的下面就是菜單列表。
MVP的實(shí)現(xiàn):開發(fā)技術(shù)前線APP
MVP與Activity恐仑、Fragment的生命周期:
由于Presenter持有了MainActivity的強(qiáng)引用泉坐,如果在請(qǐng)求結(jié)束之前Activity被銷毀,那么由于網(wǎng)絡(luò)請(qǐng)求還沒有返回裳仆,會(huì)導(dǎo)致內(nèi)存泄露腕让。可以通過弱引用和Activity歧斟、Fragment的生命周期來解決這個(gè)問題记某。首先建立一個(gè)Presenter抽象類,View類型通過這個(gè)抽象類的泛型傳遞進(jìn)來构捡,Presenter對(duì)這個(gè)View持有弱引用液南。然后創(chuàng)建一個(gè)MVPBaseAcitivity基類,通過這個(gè)基類的生命周期函數(shù)來控制它與Presenter的關(guān)系勾徽。
public abstract class BasePresenter<T> {
protected Reference<T> mViewRef;
public void aatchView(T view) {
mViewRef = new WeakReference<T>(view);
}
protected T getView() {
return mViewRef.get();
}
public boolean isViewAttached() {
return mViewRef != null && mviewRef.get != null;
}
public void detachView() {
if(mViewRef != null) {
mViewRef.clear();
mViewRef = null;
}
}
}
public abstract class MVPBaseActivity<V,Textends BasePresenter<V>extends Activity {
protected T mPresenter;
@SuppressWarnings("unchecked")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mPresenter = createPresenter();
mPresenter.accachView((V) this);
}
@Override
protected void onDestroy() {
super.onDestroy();
mPresenter.detachView();
}
protected abstract T cratePresenter();
}
二十七滑凉、MVVM應(yīng)用淺析
介紹:MVVC與MVC、MVP的本質(zhì)是一樣的,都是將邏輯分層解耦的產(chǎn)物畅姊,與MVP不同的是咒钟,在ViewModel中有一個(gè)叫做Binder或DataBinding Engine的東西,之間在MVP中由Presenter負(fù)責(zé)的View和Model之間的數(shù)據(jù)邏輯操作就交給這個(gè)Binder去處理若未,而在View中我們只需要聲明View上顯示的內(nèi)容是Model的哪一塊數(shù)據(jù)朱嘴,將其與之綁定在一起即可,最后當(dāng)ViewModel對(duì)Model層的相關(guān)數(shù)據(jù)進(jìn)行更新的時(shí)候粗合,Binder會(huì)將更新后的數(shù)據(jù)傳遞給View萍嬉,View則根據(jù)新的數(shù)據(jù)刷新自己,同樣地隙疚,當(dāng)用戶對(duì)View層操作的時(shí)候壤追,如果涉及對(duì)數(shù)據(jù)的更新,Binder同樣也會(huì)把數(shù)據(jù)更新到Model層供屉。
MVVM的基本結(jié)構(gòu)
Model:MVVM的Model層與MVC行冰、MVP沒太大區(qū)別,也主要是封裝數(shù)據(jù)存儲(chǔ)或操作的一些邏輯伶丐,與兩者不同的是Model會(huì)提供一系列的實(shí)體類用作與UI進(jìn)行綁定悼做,ViewModel則會(huì)在修改這些數(shù)據(jù)后將數(shù)據(jù)變化告訴View層并使UI刷新
View:View層與MVC、MVP一樣哗魂,都是用于處理界面的邏輯且不參與業(yè)務(wù)邏輯相關(guān)的操作肛走,只負(fù)責(zé)顯示由ViewModel提供的數(shù)據(jù)
ViewModel:本質(zhì)是視圖模型與視圖狀態(tài)的全稱,其主要職責(zé)就是為View層提供一個(gè)可供其顯示的數(shù)據(jù)模型并且同時(shí)搜集啡彬、處理這些數(shù)據(jù)
View與ViewModel之間的交互:Binder的實(shí)現(xiàn)除第三方框架外,還有Command命令模式故硅,View和ViewModel分別可以看作是:Invoker和Receiver
MVVM在Android中的應(yīng)用與DataBinding使用淺析:
//集成DataBinding庶灿,在Module的build.gradle文件中添加如下代碼:
dataBinding {
enabled = true
}
//修改布局文件
<?xml version="1.0" encoding="utf-8"?>
<layout
xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<import type="com.lewanjiang.mvvmtest.User" />
<variable
name="user"
type="com.lewanjiang.mvvmtest.User" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@(User.fistName)"
android:textSize="20sp"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@(user.lastName)"
android:textSize="25sp"/>
</LinearLayout>
</layout>
//定義實(shí)體類
public class User {
private String firstName;
private String lastName;
public User(String firstName,String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
}
//修改MainActivity
public class MainActivity extends AppCompatActivity {
private ActivityMainBinding mActivityMainBinding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mActivityMainBinding = DataBindingUtil.setContentView(this,R.layout.activity_main);
User user = new User("bob","Jiang");
mActivityMainBinding.setUser(user);
}
}
MVVM的優(yōu)缺點(diǎn)
優(yōu)點(diǎn):相對(duì)于MVP而言,不需要手動(dòng)去處理大師的View和Model相關(guān)的操作吃衅,因?yàn)殡p向綁定往踢,只需要保證Model正確,那么View就一定是正確的徘层,讓測(cè)試變得簡(jiǎn)單
MVC峻呕、MVP與MVVM的異同
二十八、易混淆的設(shè)計(jì)模式
簡(jiǎn)單工廠趣效、工廠方法瘦癌、抽象工廠、Builder模式的區(qū)別
簡(jiǎn)單工廠:一個(gè)工廠方法創(chuàng)建不同類型的對(duì)象
工廠方法:一個(gè)具體的工廠類負(fù)責(zé)創(chuàng)建一個(gè)具體對(duì)象類型
抽象工廠跷敬、一個(gè)具體的工廠類負(fù)責(zé)創(chuàng)建一系列相關(guān)的對(duì)象
Builder:對(duì)象的構(gòu)建與表示分享讯私,它更注重對(duì)象的創(chuàng)建過程
代理與裝飾模式、橋接模式
代理模式:為其他對(duì)象提供一種代理以控制對(duì)這個(gè)對(duì)象的訪問
裝飾模式:動(dòng)態(tài)地給一個(gè)對(duì)象添加一些額外的職責(zé)。就增加功能來說斤寇,裝飾模式相比生成子類更為靈活
橋接模式:將抽象和實(shí)現(xiàn)解耦桶癣,使得兩者可以獨(dú)立地變化
外觀模式與中介模式
外觀模式:要求一個(gè)子系統(tǒng)的外部與其內(nèi)部的通信必須通過一個(gè)統(tǒng)一的對(duì)象進(jìn)行。外觀模式提供一個(gè)高層次的接口娘锁,使得子系統(tǒng)更易于使用牙寞。
中介模式:用一個(gè)中介對(duì)象封裝一系列的對(duì)象交互,中介者使各對(duì)象不需要顯示地相互作用莫秆,從而使其耦合松散间雀,而且可以獨(dú)立地改變它們之間的交互。
策略與狀態(tài)模式馏锡、命令模式
策略模式:定義一組算法雷蹂,將每個(gè)算法都封裝進(jìn)來,并且使它們之間可以互換
狀態(tài)模式:當(dāng)一個(gè)對(duì)象內(nèi)在狀態(tài)改變時(shí)允許其改變行為杯道,這個(gè)對(duì)象看起來介改變了其類匪煌。
命令模式:將一個(gè)請(qǐng)求封裝成一個(gè)對(duì)象,從而讓你使用不同的請(qǐng)求把客戶端參數(shù)化党巾,對(duì)請(qǐng)求排隊(duì)或者記錄請(qǐng)求日志萎庭,可以提供命令的撤銷和恢復(fù)功能。