前言
Android的設(shè)計(jì)模式系列文章介紹,歡迎關(guān)注,持續(xù)更新中:
Android的設(shè)計(jì)模式-設(shè)計(jì)模式的六大原則
一句話總結(jié)23種設(shè)計(jì)模式則
創(chuàng)建型模式:
Android的設(shè)計(jì)模式-單例模式
Android的設(shè)計(jì)模式-建造者模式
Android的設(shè)計(jì)模式-工廠方法模式
Android的設(shè)計(jì)模式-簡(jiǎn)單工廠模式
Android的設(shè)計(jì)模式-抽象工廠模式
Android的設(shè)計(jì)模式-原型模式
行為型模式:
Android的設(shè)計(jì)模式-策略模式
Android的設(shè)計(jì)模式-狀態(tài)模式
Android的設(shè)計(jì)模式-責(zé)任鏈模式
Android的設(shè)計(jì)模式-觀察者模式
Android的設(shè)計(jì)模式-模板方法模式
Android的設(shè)計(jì)模式-迭代器模式
Android的設(shè)計(jì)模式-備忘錄模式
Android的設(shè)計(jì)模式-訪問(wèn)者模式
Android的設(shè)計(jì)模式-中介者模式
Android的設(shè)計(jì)模式-解釋器模式
Android的設(shè)計(jì)模式-命令模式
結(jié)構(gòu)型模式:
Android的設(shè)計(jì)模式-代理模式
Android的設(shè)計(jì)模式-組合模式
Android的設(shè)計(jì)模式-適配器模式
Android的設(shè)計(jì)模式-裝飾者模式
Android的設(shè)計(jì)模式-享元模式
Android的設(shè)計(jì)模式-外觀模式
Android的設(shè)計(jì)模式-橋接模式
1.定義
在不破壞封裝性的前提下,捕獲一個(gè)對(duì)象的內(nèi)部狀態(tài),并在該對(duì)象之外保存這個(gè)狀態(tài),這樣以后就可以將該對(duì)象恢復(fù)到先前保存的狀態(tài)。
2.介紹
- 備忘錄模式屬于行為型模式。
- 備忘錄模式比較適合用于功能復(fù)雜,但是需要維護(hù)和紀(jì)錄歷史的地方,或者是需要保存一個(gè)或者多個(gè)屬性的地方;在未來(lái)某個(gè)時(shí)刻需要時(shí),將其還原到原來(lái)紀(jì)錄的狀態(tài)。
3.UML類圖

角色說(shuō)明:
- Originator(發(fā)起人角色):負(fù)責(zé)創(chuàng)建一個(gè)備忘錄(Memoto),能夠記錄內(nèi)部狀態(tài),以及恢復(fù)原來(lái)記錄的狀態(tài)。并且能夠決定哪些狀態(tài)是需要備忘的。
- Memoto(備忘錄角色):將發(fā)起人(Originator)對(duì)象的內(nèi)部狀態(tài)存儲(chǔ)起來(lái);并且可以防止發(fā)起人(Originator)之外的對(duì)象訪問(wèn)備忘錄(Memoto)。
- Caretaker(負(fù)責(zé)人角色):負(fù)責(zé)保存?zhèn)渫洠∕emoto),不能對(duì)備忘錄(Memoto)的內(nèi)容進(jìn)行操作和訪問(wèn),只能將備忘錄傳遞給其他對(duì)象。
4.實(shí)現(xiàn)
以游戲存檔為例子:
4.1 創(chuàng)建發(fā)起人角色
這里則是游戲類,游戲類提供存檔和讀檔的功能:
public class Game {//游戲類
private int mLevel = 1;//等級(jí)
private int mCoin = 0;//金幣數(shù)量
@Override
public String toString() {
return "game{" +
"mLevel=" + mLevel +
", mCoin=" + mCoin +
'}';
}
public void play() {
System.out.println("升級(jí)了");
mLevel++;
System.out.println("當(dāng)前等級(jí)為:" + mLevel);
System.out.println("獲得金幣:32");
mCoin += 32;
System.out.println("當(dāng)前金幣數(shù)量為:" + mCoin);
}
public void exit() {
System.out.println("退出游戲");
System.out.println("退出游戲時(shí)的屬性 : " + 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)建備忘錄角色
負(fù)責(zé)將游戲類的內(nèi)部狀態(tài)存儲(chǔ)起來(lái):
public class Memento {//備忘錄類
public int level;//等級(jí)
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)建負(fù)責(zé)人角色
負(fù)責(zé)保存?zhèn)渫?,不能?duì)備忘錄的內(nèi)容進(jìn)行操作和訪問(wèn),只能將備忘錄傳遞給其他對(duì)象。
public class Caretaker {//備忘錄管理類
private Memento mMemento;
public void setMemento(Memento memento) {
mMemento = memento;
}
public Memento getMemento() {
return mMemento;
}
}
4.4 客戶端測(cè)試
public void test() {
System.out.println("首次進(jìn)入游戲");
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("二次進(jìn)入游戲");
Game secondGame = new Game();
secondGame.setMemento(caretaker.getMemento());//讀取存檔
secondGame.play();//繼續(xù)玩游戲
secondGame.exit();//不存檔,嘿嘿嘿
}
輸出結(jié)果:
首次進(jìn)入游戲
升級(jí)了
當(dāng)前等級(jí)為:2
獲得金幣:32
當(dāng)前金幣數(shù)量為:32
退出游戲
退出游戲時(shí)的屬性 : game{mLevel=2, mCoin=32}
-------------
二次進(jìn)入游戲
讀取存檔信息:game{mLevel=2, mCoin=32}
升級(jí)了
當(dāng)前等級(jí)為:3
獲得金幣:32
當(dāng)前金幣數(shù)量為:64
退出游戲
退出游戲時(shí)的屬性 : game{mLevel=3, mCoin=64}
5. 應(yīng)用場(chǎng)景
- 需要保存對(duì)象的某一時(shí)刻的狀態(tài)時(shí)
6. 優(yōu)點(diǎn)
- 能夠讓狀態(tài)回滾到某一時(shí)刻的狀態(tài)
- 實(shí)現(xiàn)了狀態(tài)保存對(duì)象的封裝,用戶無(wú)需關(guān)心其實(shí)現(xiàn)細(xì)節(jié)。
7. 缺點(diǎn)
- 要保存的對(duì)象如果成員變量過(guò)多的話,資源消耗也會(huì)相應(yīng)增多。
8. Android中的源碼分析
Android中的Activity就提供了狀態(tài)保存機(jī)制來(lái)保證Activity在被系統(tǒng)回收后能夠恢復(fù)當(dāng)前Activity的數(shù)據(jù)。這一機(jī)制實(shí)際上就是onSaveInstanceState和onRestoreInstanceState。onSaveInstanceState就是用來(lái)保存當(dāng)前Activity的狀態(tài),onRestoreInstanceState則是用來(lái)恢復(fù)Activity的狀態(tài)。
8.1 onSaveInstanceState 源碼
protected void onSaveInstanceState(Bundle outState) {//保存各種狀態(tài)
//1.保存Activity對(duì)應(yīng)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),那么會(huì)調(diào)用ActivityLifecycleCallbacks的onSaveInstanceState來(lái)進(jìn)行保存狀態(tài)信息
getApplication().dispatchActivitySaveInstanceState(this, outState);
}
8.2 onRestoreInstanceState 源碼
protected void onRestoreInstanceState(Bundle savedInstanceState) {
if (mWindow != null) {
//獲取保存過(guò)的window狀態(tài)信息
Bundle windowState = savedInstanceState.getBundle(WINDOW_HIERARCHY_TAG);
//如果存在狀態(tài)信息,則window進(jìn)行恢復(fù)
if (windowState != null) {
mWindow.restoreHierarchyState(windowState);
}
}
}
8.3 總結(jié)
-
Activity的狀態(tài)保存與恢復(fù)其實(shí)是個(gè)比較復(fù)雜的東西,很多細(xì)節(jié)這里都沒(méi)說(shuō)到,有興趣的同學(xué)可以找相關(guān)資料研究下,這里主要還是講設(shè)計(jì)模式在Android源碼中的應(yīng)用。 - 在上面的源碼中,
Activity實(shí)際上就是負(fù)責(zé)人角色(Caretaker),負(fù)責(zé)保存和恢復(fù)UI信息;Activity、View、ViewGroup、Fragment等都是發(fā)起人角色(Originator),他們各自負(fù)責(zé)需要保存的信息;而備忘錄角色(Memoto)則是Bundle類了,相關(guān)狀態(tài)信息都是保存在Bundle中。 - 此外,
Canvas中的Save()和Restore()也是使用到了備忘錄模式,有興趣的可以去看下。
相關(guān)文章閱讀
Android的設(shè)計(jì)模式-設(shè)計(jì)模式的六大原則
一句話總結(jié)23種設(shè)計(jì)模式則
創(chuàng)建型模式:
Android的設(shè)計(jì)模式-單例模式
Android的設(shè)計(jì)模式-建造者模式
Android的設(shè)計(jì)模式-工廠方法模式
Android的設(shè)計(jì)模式-簡(jiǎn)單工廠模式
Android的設(shè)計(jì)模式-抽象工廠模式
Android的設(shè)計(jì)模式-原型模式
行為型模式:
Android的設(shè)計(jì)模式-策略模式
Android的設(shè)計(jì)模式-狀態(tài)模式
Android的設(shè)計(jì)模式-責(zé)任鏈模式
Android的設(shè)計(jì)模式-觀察者模式
Android的設(shè)計(jì)模式-模板方法模式
Android的設(shè)計(jì)模式-迭代器模式
Android的設(shè)計(jì)模式-備忘錄模式
Android的設(shè)計(jì)模式-訪問(wèn)者模式
Android的設(shè)計(jì)模式-中介者模式
Android的設(shè)計(jì)模式-解釋器模式
Android的設(shè)計(jì)模式-命令模式
結(jié)構(gòu)型模式:
Android的設(shè)計(jì)模式-代理模式
Android的設(shè)計(jì)模式-組合模式
Android的設(shè)計(jì)模式-適配器模式
Android的設(shè)計(jì)模式-裝飾者模式
Android的設(shè)計(jì)模式-享元模式
Android的設(shè)計(jì)模式-外觀模式
Android的設(shè)計(jì)模式-橋接模式