“狀态變化”模式
- 在元件建構過程中,某些對象的狀态經常面臨變化,如何對這些變化進行有效的管理?同時又維持高層子產品的穩定?“狀态變化"模式為這一問題提供了一種解決方案。
- 典型模式
- State
- Memento
動機(Motivation)
- 在軟體建構過程中,某些對象的狀态在轉換過程中,可能由于某種需要,要求程式能夠回溯到對象之前處于某個點時的狀态。如果使用一些公有接口來讓其他對象得到對象的狀态,便會暴露對象的細節實作。
- 如何實作對象狀态的良好儲存與恢複?但同時又不會是以而破壞對象本身的封裝性。
模式定義
在不破壞封裝性的前提下,捕獲一個對象的内部狀态,并在該對象之外儲存這個狀态。這樣以後就可以将該對象恢複到原先儲存的狀态。——《設計模式》GoF
// 原理思想很簡單,具體的實作有可能是很複雜的,儲存一次或儲存N次。
示例
#include <iostream>
#include <string>
using namespace std;
class Memento
{
string state;
//...
public:
Memento(const string & s) : state(s) {}
string getState() const { return state; }
void setState(const string & s) { state = s; }
};
// 這個是穩定的,不破壞它的封裝
class Originator
{
string state;
//....
public:
Originator() {}
Memento createMomento() {
Memento m(state); // 現實實作中,内部有可能非常複雜。
return m;
}
void setMomento(const Memento & m) {
state = m.getState();
}
void showState() {
cout << state << endl;
}
void setState(string str) {
state = str;
}
};
int main()
{
Originator orginator;
orginator.setState("晴天");
orginator.showState();
//捕獲對象狀态,存儲到備忘錄 拍個快照
Memento mem = orginator.createMomento();
//... 改變orginator狀态
orginator.setState("晴轉多雲");
orginator.showState();
orginator.setState("西北雨");
orginator.showState();
//從備忘錄中恢複
orginator.setMomento(mem);
orginator.showState();
getchar();
return 0;
}
輸出:
晴天
晴轉多雲
西北雨
晴天
類圖
要點總結
- 備忘錄(Memento)存儲原發器(Originator)對象的内部狀态,在需要時恢複原發器狀态。
- Memento模式的核心是資訊隐藏,即Originator需要向外接隐藏資訊,保持其封裝性。但同時又需要将狀态保持到外界(Memento)。
- 由于現代語言運作時(如C#、Java等)都具有相當的對象序列化支援,是以往往采用效率較高、又較容易正确實作的序列化方案來實作Memento模式。//是以,這個設計模式有點過時。
今天,語言和架構提供了我們非常友善和高效的方式,這個模式在 94 年。