前言
Android的設(shè)計模式系列文章介紹,歡迎關(guān)注印荔,持續(xù)更新中:
Android的設(shè)計模式-設(shè)計模式的六大原則
一句話總結(jié)23種設(shè)計模式則
創(chuàng)建型模式:
Android的設(shè)計模式-單例模式
Android的設(shè)計模式-建造者模式
Android的設(shè)計模式-工廠方法模式
Android的設(shè)計模式-簡單工廠模式
Android的設(shè)計模式-抽象工廠模式
Android的設(shè)計模式-原型模式
行為型模式:
Android的設(shè)計模式-策略模式
Android的設(shè)計模式-狀態(tài)模式
Android的設(shè)計模式-責任鏈模式
Android的設(shè)計模式-觀察者模式
Android的設(shè)計模式-模板方法模式
Android的設(shè)計模式-迭代器模式
Android的設(shè)計模式-備忘錄模式
Android的設(shè)計模式-訪問者模式
Android的設(shè)計模式-中介者模式
Android的設(shè)計模式-解釋器模式
Android的設(shè)計模式-命令模式
結(jié)構(gòu)型模式:
Android的設(shè)計模式-代理模式
Android的設(shè)計模式-組合模式
Android的設(shè)計模式-適配器模式
Android的設(shè)計模式-裝飾者模式
Android的設(shè)計模式-享元模式
Android的設(shè)計模式-外觀模式
Android的設(shè)計模式-橋接模式
1.定義
在不破壞封裝性的前提下,捕獲一個對象的內(nèi)部狀態(tài)将鸵,并在該對象之外保存這個狀態(tài)粗仓,這樣以后就可以將該對象恢復到先前保存的狀態(tài)譬挚。
2.介紹
- 備忘錄模式屬于行為型模式。
- 備忘錄模式比較適合用于功能復雜刃唐,但是需要維護和紀錄歷史的地方羞迷,或者是需要保存一個或者多個屬性的地方界轩;在未來某個時刻需要時,將其還原到原來紀錄的狀態(tài)衔瓮。
3.UML類圖
角色說明:
- Originator(發(fā)起人角色):負責創(chuàng)建一個備忘錄(Memoto)浊猾,能夠記錄內(nèi)部狀態(tài),以及恢復原來記錄的狀態(tài)热鞍。并且能夠決定哪些狀態(tài)是需要備忘的葫慎。
- Memoto(備忘錄角色):將發(fā)起人(Originator)對象的內(nèi)部狀態(tài)存儲起來;并且可以防止發(fā)起人(Originator)之外的對象訪問備忘錄(Memoto)碍现。
- Caretaker(負責人角色):負責保存?zhèn)渫洠∕emoto)幅疼,不能對備忘錄(Memoto)的內(nèi)容進行操作和訪問,只能將備忘錄傳遞給其他對象昼接。
4.實現(xiàn)
以游戲存檔為例子:
4.1 創(chuàng)建發(fā)起人角色
這里則是游戲類爽篷,游戲類提供存檔和讀檔的功能:
public class Game {//游戲類
private int mLevel = 1;//等級
private int mCoin = 0;//金幣數(shù)量
@Override
public String toString() {
return "game{" +
"mLevel=" + mLevel +
", mCoin=" + mCoin +
'}';
}
public void play() {
System.out.println("升級了");
mLevel++;
System.out.println("當前等級為:" + mLevel);
System.out.println("獲得金幣:32");
mCoin += 32;
System.out.println("當前金幣數(shù)量為:" + mCoin);
}
public void exit() {
System.out.println("退出游戲");
System.out.println("退出游戲時的屬性 : " + toString());
}
public Memento createMemento() {//創(chuàng)建備忘錄,即游戲存檔
Memento memento = new Memento();
memento.setLevel(mLevel);
memento.setCoin(mCoin);
return memento;
}
public void setMemento(Memento memento) {
mLevel = memento.getLevel();
mCoin = memento.getCoin();
System.out.println("讀取存檔信息:" + toString());
}
}
4.2 創(chuàng)建備忘錄角色
負責將游戲類的內(nèi)部狀態(tài)存儲起來:
public class Memento {//備忘錄類
public int level;//等級
public int coin;//金幣數(shù)量
public void setLevel(int level) {
this.level = level;
}
public void setCoin(int coin) {
this.coin = coin;
}
public int getLevel() {
return level;
}
public int getCoin() {
return coin;
}
}
4.3 創(chuàng)建負責人角色
負責保存?zhèn)渫洠荒軐渫浀膬?nèi)容進行操作和訪問慢睡,只能將備忘錄傳遞給其他對象逐工。
public class Caretaker {//備忘錄管理類
private Memento mMemento;
public void setMemento(Memento memento) {
mMemento = memento;
}
public Memento getMemento() {
return mMemento;
}
}
4.4 客戶端測試
public void test() {
System.out.println("首次進入游戲");
Game game = new Game();
game.play();//玩游戲
Memento memento = game.createMemento();//創(chuàng)建存檔
Caretaker caretaker = new Caretaker();
caretaker.setMemento(memento);//保存存檔
game.exit();//退出游戲
System.out.println("-------------");
System.out.println("二次進入游戲");
Game secondGame = new Game();
secondGame.setMemento(caretaker.getMemento());//讀取存檔
secondGame.play();//繼續(xù)玩游戲
secondGame.exit();//不存檔,嘿嘿嘿
}
輸出結(jié)果:
首次進入游戲
升級了
當前等級為:2
獲得金幣:32
當前金幣數(shù)量為:32
退出游戲
退出游戲時的屬性 : game{mLevel=2, mCoin=32}
-------------
二次進入游戲
讀取存檔信息:game{mLevel=2, mCoin=32}
升級了
當前等級為:3
獲得金幣:32
當前金幣數(shù)量為:64
退出游戲
退出游戲時的屬性 : game{mLevel=3, mCoin=64}
5. 應用場景
- 需要保存對象的某一時刻的狀態(tài)時
6. 優(yōu)點
- 能夠讓狀態(tài)回滾到某一時刻的狀態(tài)
- 實現(xiàn)了狀態(tài)保存對象的封裝,用戶無需關(guān)心其實現(xiàn)細節(jié)漂辐。
7. 缺點
- 要保存的對象如果成員變量過多的話泪喊,資源消耗也會相應增多。
8. Android中的源碼分析
Android中的Activity
就提供了狀態(tài)保存機制來保證Activity
在被系統(tǒng)回收后能夠恢復當前Activity
的數(shù)據(jù)髓涯。這一機制實際上就是onSaveInstanceState
和onRestoreInstanceState
袒啼。onSaveInstanceState
就是用來保存當前Activity
的狀態(tài),onRestoreInstanceState
則是用來恢復Activity
的狀態(tài)纬纪。
8.1 onSaveInstanceState 源碼
protected void onSaveInstanceState(Bundle outState) {//保存各種狀態(tài)
//1.保存Activity對應Window的狀態(tài)信息
outState.putBundle(WINDOW_HIERARCHY_TAG, mWindow.saveHierarchyState());
//2.如果存在Fragments,則保存所有Fragments的狀態(tài)信息
Parcelable p = mFragments.saveAllState();
if (p != null) {
outState.putParcelable(FRAGMENTS_TAG, p);
}
//3.如果設(shè)置了ActivityLifecycleCallbacks回調(diào),那么會調(diào)用ActivityLifecycleCallbacks的onSaveInstanceState來進行保存狀態(tài)信息
getApplication().dispatchActivitySaveInstanceState(this, outState);
}
8.2 onRestoreInstanceState 源碼
protected void onRestoreInstanceState(Bundle savedInstanceState) {
if (mWindow != null) {
//獲取保存過的window狀態(tài)信息
Bundle windowState = savedInstanceState.getBundle(WINDOW_HIERARCHY_TAG);
//如果存在狀態(tài)信息蚓再,則window進行恢復
if (windowState != null) {
mWindow.restoreHierarchyState(windowState);
}
}
}
8.3 總結(jié)
-
Activity
的狀態(tài)保存與恢復其實是個比較復雜的東西,很多細節(jié)這里都沒說到包各,有興趣的同學可以找相關(guān)資料研究下摘仅,這里主要還是講設(shè)計模式在Android源碼中的應用。 - 在上面的源碼中问畅,
Activity
實際上就是負責人角色(Caretaker
)娃属,負責保存和恢復UI信息;Activity
护姆、View
矾端、ViewGroup
、Fragment
等都是發(fā)起人角色(Originator
)卵皂,他們各自負責需要保存的信息须床;而備忘錄角色(Memoto
)則是Bundle
類了,相關(guān)狀態(tài)信息都是保存在Bundle
中渐裂。 - 此外豺旬,
Canvas
中的Save()
和Restore()
也是使用到了備忘錄模式,有興趣的可以去看下柒凉。
相關(guān)文章閱讀
Android的設(shè)計模式-設(shè)計模式的六大原則
一句話總結(jié)23種設(shè)計模式則
創(chuàng)建型模式:
Android的設(shè)計模式-單例模式
Android的設(shè)計模式-建造者模式
Android的設(shè)計模式-工廠方法模式
Android的設(shè)計模式-簡單工廠模式
Android的設(shè)計模式-抽象工廠模式
Android的設(shè)計模式-原型模式
行為型模式:
Android的設(shè)計模式-策略模式
Android的設(shè)計模式-狀態(tài)模式
Android的設(shè)計模式-責任鏈模式
Android的設(shè)計模式-觀察者模式
Android的設(shè)計模式-模板方法模式
Android的設(shè)計模式-迭代器模式
Android的設(shè)計模式-備忘錄模式
Android的設(shè)計模式-訪問者模式
Android的設(shè)計模式-中介者模式
Android的設(shè)計模式-解釋器模式
Android的設(shè)計模式-命令模式
結(jié)構(gòu)型模式:
Android的設(shè)計模式-代理模式
Android的設(shè)計模式-組合模式
Android的設(shè)計模式-適配器模式
Android的設(shè)計模式-裝飾者模式
Android的設(shè)計模式-享元模式
Android的設(shè)計模式-外觀模式
Android的設(shè)計模式-橋接模式