设计模式之备忘录模式(Memento)摘录
Memento:(1)、意图:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。
(2)、适用性:A、必须保存一个对象在某一个时刻的(部分)状态,这样以后需要时它才能恢复到先前的状态。B、如果一个用接口来让其它对象直接得到这些状态,将会暴露对象的实现细节并破坏对象的封装性。
(3)、效果:
A、保持封装边界:使用备忘录可以避免暴露一些只应由原发器管理却又必须存储在原发器之外的信息。该模式把可能很复杂的Originator内部信息对其他对象屏蔽起来,从而保持了封装边界。
B、它简化了原发器:在其他的保持封装性的设计中,Originator负责保持客户请求过的内部状态版本。这就把所有存储管理的重任交给了Originator。让客户管理它们请求的状态将会简化Originator,并且使得客户工作结束时无需通知原发器。
C、使用备忘录可能代价很高:如果原发器在生成备忘录时必须拷贝并存储大量的信息,或者客户非常频繁地创建备忘录和恢复原发器状态,可能会导致非常大的开销。除非封装和恢复Originator状态的开销不大,否则该模式可能并不合适。
D、定义窄接口和宽接口:在一些语言中可能难以保证只有原发器可访问备忘录的状态。
E、维护备忘录的潜在代价:管理器负责删除它所维护的备忘录。然而,管理器不知道备忘录中有多少个状态。因此当存储备忘录时,一个本来很小的管理器,可能会产生大量的存储开销。
(4)、相关模式:A、Command:命令可使用备忘录来为可撤销的操作维护状态。B、Iterator:备忘录可用于迭代。
(5)、备忘录模式:适用于功能比较复杂的,但需要记录或维护属性历史的类;或者需要保存的属性只是众多属性中的一小部分时Originator可以根据保存的Memo还原到前一状态。
示例代码1:
#include <iostream> #include <string> using namespace std; class Memo; //发起人类 class Originator { public: string state; Memo* CreateMemo(); void SetMemo(Memo* memo); void Show() { cout<<"状态"<<state<<endl; } }; //备忘录类 class Memo { public: string state; Memo(string strState) { state = strState; } }; Memo* Originator::CreateMemo() { return new Memo(state); } void Originator::SetMemo(Memo* memo) { state = memo->state; } //管理者类 class Caretaker { public: Memo* memo; }; //客户端 int main() { Originator* on = new Originator(); on->state = "on"; on->Show(); Caretaker* c = new Caretaker(); c->memo = on->CreateMemo(); on->state = "off"; on->Show(); on->SetMemo(c->memo); on->Show(); /*result 状态on 状态off 状态on */ return 0; } |
示例代码2:
Memento.h:
#ifndef _MEMENTO_H_ #define _MEMENTO_H_ #include <string> using namespace std; class Memento; class Originator { public: typedef string State; Originator(); Originator(const State& sdt); ~Originator(); Memento* CreateMemento(); void SetMemento(Memento* men); void RestoreToMemento(Memento* mt); State GetState(); void SetState(const State& sdt); void PrintState(); protected: private: State _sdt; Memento* _mt; }; class Memento { public: protected: private: //这是最关键的地方,将Originator为friend类,可以访问内部信息,但是其他类不能访问 friend class Originator; typedef string State; Memento(); Memento(const State& sdt); ~Memento(); void SetState(const State& sdt); State GetState(); private: State _sdt; }; #endif//~_MEMENTO_H_ |
Memento.cpp:
#include "Memento.h" #include <iostream> using namespace std; typedef string State; Originator::Originator() { _sdt = ""; _mt = 0; } Originator::Originator(const State& sdt) { _sdt = sdt; _mt = 0; } Originator::~Originator() { } Memento* Originator::CreateMemento() { return new Memento(_sdt); } State Originator::GetState() { return _sdt; } void Originator::SetState(const State& sdt) { _sdt = sdt; } void Originator::PrintState() { cout<<this->_sdt<<"... ..."<<endl; } void Originator::SetMemento(Memento* men) { } void Originator::RestoreToMemento(Memento* mt) { this->_sdt = mt->GetState(); } //class Memento Memento::Memento() { } Memento::Memento(const State& sdt) { _sdt = sdt; } State Memento::GetState() { return _sdt; } void Memento::SetState(const State& sdt) { _sdt = sdt; } |
main.cpp:
#include "Memento.h" #include <iostream> using namespace std; int main() { Originator* o = new Originator(); o->SetState("old");//备忘前状态 o->PrintState(); Memento* m = o->CreateMemento();//将状态备忘 o->SetState("new");//修改状态 o->PrintState(); o->RestoreToMemento(m);//恢复修改前状态 o->PrintState(); /*result old... ... new... ... old... ... */ return 0; } |
备忘录模式结构图:
设计模式之中介者模式(Mediator)摘录
Mediator:(1)、意图:用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
(2)、适用性:A、一组对象以定义良好但是复杂的方式进行通信。产生的相互依赖关系结构混乱且难以理解。B、一个对象引用其他很多对象并且直接与这些对象通信,导致难以复用该对象。C、想定制一个分布在多个类中的行为,而又不想生成太多的子类。
(3)、优缺点:
A、减少了子类生成:Mediator将原本分布于多个对象间的行为集中在一起。改变这些行为只需生成Mediator的子类即可。这样各个Colleague类可被重用。
B、它将各Colleague解耦:Mediator有利于各Colleague间的松耦合。你可以独立的改变和复用各Colleague类和Mediator类。
C、它简化了对象协议:用Mediator和各Colleague间的一对多的交互来代替多对多的交互。一对多的关系更易于理解、维护和扩展。
D、它对对象如何协作进行了抽象:将中介作为一个独立的概念并将其封装在一个对象中,使你将注意力从对象各自本身的行为转移到它们之间的交互上来。这有助于弄清楚一个系统中的对象是如何交互的。
E、它使控制集中化:中介者模式将交互的复杂性变为中介者的复杂性。因为中介者封装了协议,它可能变得比任一个Colleague都复杂。这可能使得中介者自身成为一个难于维护的庞然大物。
(4)、相关模式:A、Facade与中介者的不同之处在于它是对一个对象子系统进行抽象,从而提供了一个更为方便的接口。它的协议是单向的,即Facade对象对这个子系统类提出请求,但反之则不行。相反,Mediator提供了各Colleague对象不支持或不能支持的协作行为,而且协议是多向的。B、Colleague可使用Observer模式与Mediator通信。
(5)、Mediator模式提供将对象间的交互和通讯封装在一个类中,各个对象间的通信不必显式去声明和引用,大大降低了系统的复杂性能。另外,Mediator模式还带来了系统对象间的松耦合。
示例代码1:
#include <iostream> #include <string> #include <vector> using namespace std; class Colleague; //中介者类 class Mediator { public: virtual void Send(string message, Colleague* col) = 0; }; //抽象同事类 class Colleague { protected: Mediator* mediator; public: Colleague(Mediator* temp) { mediator = temp; } }; //同事一 class Colleague1 : public Colleague { public: Colleague1(Mediator* media) : Colleague(media) {} void Send(string strMessage) { mediator->Send(strMessage, this); } void Notify(string strMessage) { cout<<"同事一获得了消息"<<strMessage<<endl; } }; //同事二 class Colleague2 : public Colleague { public: Colleague2(Mediator* media) : Colleague(media) {} void Send(string strMessage) { mediator->Send(strMessage, this); } void Notify(string strMessage) { cout<<"同事二获得了消息"<<strMessage<<endl; } }; //具体中介者类 class ConcreteMediator : public Mediator { public: Colleague1* col1; Colleague2* col2; virtual void Send(string message, Colleague* col) { if (col == col1) col2->Notify(message); else col1->Notify(message); } }; //客户端 int main() { ConcreteMediator* m = new ConcreteMediator(); //让同事认识中介 Colleague1* col1 = new Colleague1(m); Colleague2* col2 = new Colleague2(m); //让中介认识具体的同事类 m->col1 = col1; m->col2 = col2; col1->Send("吃饭了吗?"); col2->Send("还没吃,你请吗?"); /*result 同事二获得了消息吃饭了吗? 同事一获得了消息还没吃,你请吗? */ return 0; } |
示例代码2:
Colleaugue.h:
#ifndef _COLLEAGUE_H_ #define _COLLEAGUE_H_ #include <string> using namespace std; class Mediator; class Colleague { public: virtual ~Colleague(); virtual void Action() = 0; virtual void SetState(const string& sdt) = 0; virtual string GetState() = 0; protected: Colleague(); Colleague(Mediator* mdt); Mediator* _mdt; private: }; class ConcreteColleagueA : public Colleague { public: ConcreteColleagueA(); ConcreteColleagueA(Mediator* mdt); ~ConcreteColleagueA(); void Action(); void SetState(const string& std); string GetState(); protected: private: string _sdt; }; class ConcreteColleagueB : public Colleague { public: ConcreteColleagueB(); ConcreteColleagueB(Mediator* mdt); ~ConcreteColleagueB(); void Action(); void SetState(const string& sdt); string GetState(); protected: private: string _sdt; }; #endif//~_COLLEAGUE_H_ |
Colleague.cpp:
#include "Mediator.h" #include "Colleague.h" #include <iostream> using namespace std; Colleague::Colleague() { //_sdt = ""; } Colleague::Colleague(Mediator* mdt) { this->_mdt = mdt; //_sdt = ""; } Colleague::~Colleague() { } ConcreteColleagueA::ConcreteColleagueA() { } ConcreteColleagueA::~ConcreteColleagueA() { } ConcreteColleagueA::ConcreteColleagueA(Mediator* mdt) : Colleague(mdt) { } string ConcreteColleagueA::GetState() { return _sdt; } void ConcreteColleagueA::SetState(const string& sdt) { _sdt = sdt; } void ConcreteColleagueA::Action() { _mdt->DoActionFromAtoB(); cout<<"State of ConcreteColleagueA:"<<this->GetState()<<endl; } ConcreteColleagueB::ConcreteColleagueB() { } ConcreteColleagueB::~ConcreteColleagueB() { } ConcreteColleagueB::ConcreteColleagueB(Mediator* mdt) : Colleague(mdt) { <div class="dp-highlighter bg_cpp"><div class="bar"><div class="tools"><b>[cpp]</b>
<a href="#" class="ViewSource" title="view plain" onclick="dp.sh.Toolbar.Command('ViewSource',this);
return false;">view plain</a><a href="#" class="CopyToClipboard" title="copy"
onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;">copy</a>
<a href="#" class="PrintSource" title="print" onclick="dp.sh.Toolbar.Command('PrintSource',this);return false;">
print</a><a href="#" class="About" title="?" onclick="dp.sh.Toolbar.Command('About',this);return false;">?</a>
<a href="https://code.csdn.net/snippets/410739" target="_blank"
title="在CODE上查看代码片" style="text-indent:0;">
<img src="https://code.csdn.net/assets/CODE_ico.png" width="12"
height="12" alt="在CODE上查看代码片" style="position:relative;top:1px;left:2px;"></a>
<a href="https://code.csdn.net/snippets/410739/fork" target="_blank"
title="派生到我的代码片" style="text-indent:0;">
<img src="https://code.csdn.net/assets/ico_fork.svg" width="12"
height="12" alt="派生到我的代码片" style="position:relative;top:2px;left:2px;"></a>
<div style="position: absolute; left: 0px; top: 0px; width: 0px; height: 0px; z-index: 99; ">
<embed id="ZeroClipboardMovie_4" src="http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf"
loop="false" menu="false" quality="best" bgcolor="#ffffff" width="0" height="0" name="ZeroClipboardMovie_4"
align="middle" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash"
pluginspage="http://www.macromedia.com/go/getflashplayer"
flashvars="id=4&width=0&height=0" wmode="transparent"></div>
</div></div><ol start="1" class="dp-cpp"><li class="alt"><span>
<span class="preprocessor">#ifndef _MEDIATOR_H_</span>
<span> </span></span></li><li class=""><span>
<span class="preprocessor">#define _MEDIATOR_H_</span><span> </span></span></li>
<li class="alt"><span> </span></li><li class="">
<span><span class="keyword">class</span>
<span> Colleague; </span></span></li><li class="alt"><span> </span></li>
<li class=""><span><span class="keyword">class</span><span> Mediator </span></span></li>
<li class="alt"><span>{ </span></li><li class=""><span><span class="keyword">public</span>
<span>: </span></span></li><li class="alt">
<span> <span class="keyword">virtual</span>
<span> ~Mediator(); </span></span></li><li class="">
<span> <span class="keyword">virtual</span><span> </span>
<span class="keyword">void</span><span> DoActionFromAtoB() = 0; </span>
</span></li><li class="alt"><span> <span class="keyword">virtual</span><span> </span>
<span class="keyword">void</span><span> DoActionFromBtoA() = 0; </span></span></li>
<li class=""><span><span class="keyword">protected</span><span>: </span></span></li><li class="alt">
<span> Mediator(); </span></li><li class="">
<span><span class="keyword">private</span><span>: </span></span></li>
<li class="alt"><span>}; </span></li><li class=""><span> </span></li>
<li class="alt"><span><span class="keyword">class</span>
<span> ConcreteMediator : </span>
<span class="keyword">public</span><span> Mediator </span>
</span></li><li class=""><span>{ </span></li><li class="alt">
<span><span class="keyword">public</span>
<span>: </span></span></li><li class="">
<span> ConcreteMediator(); </span></li>
<li class="alt"><span>
ConcreteMediator(Colleague* clgA, Colleague* clgB); </span>
</li><li class=""><span> ~ConcreteMediator(); </span></li>
<li class="alt"><span> <span class="keyword">void</span>
<span> SetConcreteColleagueA(Colleague* clgA); </span></span></li>
<li class=""><span> <span class="keyword">void</span>
<span> SetConcreteColleagueB(Colleague* clgB); </span></span></li>
<li class="alt"><span> Colleague* GetConcreteColleagueA(); </span></li>
<li class=""><span> Colleague* GetConcreteColleagueB(); </span></li>
<li class="alt"><span> <span class="keyword">void</span>
<span> IntroColleague(Colleague* clgA, Colleague* clgB); </span></span></li>
<li class=""><span> <span class="keyword">void</span>
<span> DoActionFromAtoB(); </span></span></li>
<li class="alt"><span> <span class="keyword">void</span>
<span> DoActionFromBtoA(); </span></span></li><li class="">
<span><span class="keyword">protected</span><span>: </span></span></li>
<li class="alt"><span><span class="keyword">private</span><span>: </span>
</span></li><li class=""><span> Colleague* _clgA; </span></li>
<li class="alt"><span> Colleague* _clgB; </span></li>
<li class=""><span>}; </span></li><li class="alt"><span> </span></li>
<li class=""><span><span class="preprocessor">#endif//~_MEDIATOR_H_</span>
<span> </span></span></li></ol></div>
<pre code_snippet_id="410739" snippet_file_name="blog_20140629_3_1867407"
name="code" class="cpp" style="display: none; ">#ifndef _MEDIATOR_H_ #define _MEDIATOR_H_ class Colleague; class Mediator { public: virtual ~Mediator(); virtual void DoActionFromAtoB() = 0; virtual void DoActionFromBtoA() = 0; protected: Mediator(); private: }; class ConcreteMediator : public Mediator { public: ConcreteMediator(); ConcreteMediator(Colleague* clgA, Colleague* clgB); ~ConcreteMediator(); void SetConcreteColleagueA(Colleague* clgA); void SetConcreteColleagueB(Colleague* clgB); Colleague* GetConcreteColleagueA(); Colleague* GetConcreteColleagueB(); void IntroColleague(Colleague* clgA, Colleague* clgB); void DoActionFromAtoB(); void DoActionFromBtoA(); protected: private: Colleague* _clgA; Colleague* _clgB; }; #endif//~_MEDIATOR_H_</pre><br>}void ConcreteColleagueB::Action(){_mdt->DoActionFromBtoA();
cout<<"State of ConcreteColleagueB:"<<this->GetState()<<endl;}string ConcreteColleagueB::GetState(){return _sdt;}
void ConcreteColleagueB::SetState(const string& sdt){_sdt = sdt;} |
Mediator.h:
#ifndef _MEDIATOR_H_ #define _MEDIATOR_H_ class Colleague; class Mediator { public: virtual ~Mediator(); virtual void DoActionFromAtoB() = 0; virtual void DoActionFromBtoA() = 0; protected: Mediator(); private: }; class ConcreteMediator : public Mediator { public: ConcreteMediator(); ConcreteMediator(Colleague* clgA, Colleague* clgB); ~ConcreteMediator(); void SetConcreteColleagueA(Colleague* clgA); void SetConcreteColleagueB(Colleague* clgB); Colleague* GetConcreteColleagueA(); Colleague* GetConcreteColleagueB(); void IntroColleague(Colleague* clgA, Colleague* clgB); void DoActionFromAtoB(); void DoActionFromBtoA(); protected: private: Colleague* _clgA; Colleague* _clgB; }; #endif//~_MEDIATOR_H_ |
Mediator.cpp:
#include "Mediator.h" #include "Colleague.h" Mediator::Mediator() { } Mediator::~Mediator() { } ConcreteMediator::ConcreteMediator() { } ConcreteMediator::~ConcreteMediator() { } ConcreteMediator::ConcreteMediator(Colleague* clgA, Colleague* clgB) { this->_clgA = clgA; this->_clgB = clgB; } void ConcreteMediator::DoActionFromAtoB() { _clgB->SetState(_clgA->GetState()); } void ConcreteMediator::SetConcreteColleagueA(Colleague* clgA) { this->_clgA = clgA; } void ConcreteMediator::SetConcreteColleagueB(Colleague* clgB) { this->_clgB = clgB; } Colleague* ConcreteMediator::GetConcreteColleagueA() { return _clgA; } Colleague* ConcreteMediator::GetConcreteColleagueB() { return _clgB; } void ConcreteMediator::IntroColleague(Colleague* clgA, Colleague* clgB) { this->_clgA = clgA; this->_clgB = clgB; } void ConcreteMediator::DoActionFromBtoA() { _clgA->SetState(_clgB->GetState()); } |
main.cpp:
#include "Mediator.h" #include "Colleague.h" #include <iostream> using namespace std; int main() { ConcreteMediator* m = new ConcreteMediator(); ConcreteColleagueA* c1 = new ConcreteColleagueA(m); ConcreteColleagueB* c2 = new ConcreteColleagueB(m); m->IntroColleague(c1, c2); c1->SetState("old"); c2->SetState("old"); c1->Action(); c2->Action(); cout<<endl; c1->SetState("new"); c1->Action(); c2->Action(); cout<<endl; c2->SetState("old"); c2->Action(); c1->Action(); /*result State of ConcreteColleagueA:old State of ConcreteColleagueB:old State of ConcreteColleagueA:new State of ConcreteColleagueB:new State of ConcreteColleagueB:old State of ConcreteColleagueA:old */ return 0; } |
中介者模式结构图:
|