=================================版权声明=================================
版权声明:原创文章 禁止转载
请通过右侧公告中的“联系邮箱(wlsandwho@foxmail.com)”联系我
勿用于学术性引用。
勿用于商业出版、商业印刷、商业引用以及其他商业用途。
本文不定期修正完善。
本文链接:http://www.cnblogs.com/wlsandwho/p/5124027.html
耻辱墙:http://www.cnblogs.com/wlsandwho/p/4206472.html
=======================================================================
首先交代下,这样如果这篇文章不是你想要的你就可以CTRL+W然后去找下一篇,
以免你看完整篇博客都没有了解主要功能,然后吐槽我王林森wls“什么玩意儿,还不是跟那些博客一样没什么用”。
本文并不面向“Hello World”级别的读者,该级别的读者将浪费时间然后愤愤的关闭网页,口中念念有词“什么玩意儿”。
本文不适合“I'm an 架构师”级别的读者,该级别的读者将浪费时间然后愤愤的关闭网页,口中念念有词“以其昏昏,使人昭昭”。
本文好像只适合那些刚刚看了四人帮的书急切想要弄明白怎么使用command模式做一个事务的例子的读者。或许还需要其他模式。
我王林森wlsandwho的代码实现了:
1 简单事务,即:全部成功提交,有一个失败就回滚。(在本篇中讲解实现)
2 嵌套事务,即:事务中的一个任务项可以是一个事务。(在下一篇中讲解实现)
我王林森wlsandwho的代码没有实现:
1 事务保存点,即:设置保存点后,事务只会回滚到保存点的位置而不全部回滚。(在梦中讲解实现:)
(包括但不限于上述内容)
开发环境:
Win7 64
VS 2010 SP1
Boost 1.58.0
“那你写它干嘛?”
“老来多健忘,没事写纸上。”
=======================================================================
绝大多数的设计模式文章、资料、博客都介绍了command模式,但只涉及了文字解释、结构图和让人哭笑不得的代码。(手动斜眼)
绝大多数举的代码也都是些很奇怪的东西。就算看懂了,拿过来也不能用。自己从头写又得傻一天。(手动斜眼)
绝大多数只是在最终说了一下使用command模式能够实现事务。(手动斜眼)
可是,你们到底是举个能用的例子啊。可你们不举。你们不举啊。(手动斜眼)
“我才看了几眼的设计模式啊,我着急用又没有能用的代码”。
“怎么实现的?这什么玩意到底说的什么啊?!”。
容我张狂。我王林森wlsandwho这篇博客的问世,此处省略赞美自夸之词一万字。
=======================================================================
COMMAND的结构图大家都见过,我就不画了。
这里只画我的事务小工具的简单结构图,省略N多细节。(注意,是简单结构图。)
专业画图一百年。
还是画图工具好用啊。
=======================================================================
这里得简要说一下各个部分。
=======================================================================
CTaskItemBase及其派生类,表示想要执行的任务。
你也可以用自己的类,这里只是举个例子,只要那个类支持下面的函数原型:
1 bool FuncName();
当然你需要两个,一个用来“正向操作”,一个用来“逆向操作”。
所以CTaskItemBase的接口是
1 class CTaskItemBase 2 { 3 public: 4 virtual bool Doing()=0; 5 virtual bool Undoing()=0; 6 };
例如:
你想把wlsandwho王林森的这个事务小工具用于自己的MFC对话框程序,你可以在CXXXDlg上添加bool Doing()和bool Undoing()。
然后配合命名空间中已经提供的CTransaction和CTask来完成想要的事务操作。
(我这里的CTaskItemBase、CTaskItemSample和CTaskItemSampleWithException纯粹是为了举例子做测试用的,实际使用时请换成自己的代码。)
=======================================================================
下面该轮到CTaskBase了。
光从这张简易图片看,会觉得很奇怪,“CTaskBase和CTaskItemBase是关联的,你竟然敢说‘实际使用时请换成自己的代码’?”
是的。这也是我为什么画了一张简易图,便于启发思维。(伸手党请将网页拉到底复制完整代码然后关闭本网页。)
这得益于bind。全文的一个关键点就是bind。(当然还有其他的:)
使用bind,可以接受任意类型的类成员函数和对应类对象。比单纯的设置回调函数,例如bool (*FuncName)(),要灵活一点。(仅针对本文说面向对象的部分。)
所以这里是可以的。
CTaskBase实际上是一个包装类,用于把各种不同的任务项包装成相同的样子放入指定样式的容器。Do里执行Doing,Undo里执行Undoing。
有人又要问了,那为什么不弄成仿函数或者其他的更简单的包装形式?
原因有很多,比方说“我不会”、“我懒”等等。然而其中一个原因有:不方便定制修改以及后续扩展。(至少我是这样认为的。)
(另外把两个带着类名的类成员函数、两个类对象写在一行,能想象得有多长的一行吗?分行?很难看的,而且不好意思我有强迫症。)
说到这个bind,很多人会想要用boost::bind。我也尝试过。但是在MFC里用boost::bind绑定对话框类的函数,会出现下述的错误,我表示目前能力有限也没心情调试。(奇怪的是控制台不会。)
c:\boost\boost_1_58_0\boost\function\function_base.hpp(318): error C2059: 语法错误:“reinterpret_cast”
考虑到VS2010的装机量还是很大的,我这里用了std::bind。
(题外话:我一直用98标准,所以对于新标准和新类库的采取的策略是:
先看看Boost里面有没有,有就研究下,再看看标准库里有没有,有就替换掉Boost。
不要问我为什么,没法解释。主要看心情。真的。)
=======================================================================
终于说到CTransactionBase了。
CTransaction包装了一个容器,对它遍历执行Do,如果出错就逆向遍历执行Undo。
就是这么简单。
=======================================================================
好了,解释到这里,稍微一停顿,再从头看一遍。
因为下面我王林森wlsandwho就要贴第一版代码了。
(为了简化模型、减少脑短路,所有代码不考虑声明/调用的时机以及拷贝效率、生存期、拷贝构造等问题。
你要问我“为什么”,我只能说为了让你集中注意看关键代码。)
=======================================================================
第一版代码:简单事务。
使用了Boost,无法在MFC对话框程序中使用。
示例代码为控制台程序。
1 #include <iostream> 2 #include <list> 3 #include <queue> 4 5 #include <boost/shared_ptr.hpp> 6 #include <boost/enable_shared_from_this.hpp> 7 #include <boost/bind.hpp> 8 #include <boost/function.hpp> 9 10 namespace TransactionbyWLS 11 { 12 class CTaskItemBase 13 { 14 public: 15 virtual bool Doing()=0; 16 virtual bool Undoing()=0; 17 }; 18 19 ////////////////////////////////////////////////////////////////////////// 20 //As a return-value of the function CommitOrAutoRollback. 21 enum ETransRes{ EDUMMY=0,//As a virtual function's return-value Only. 22 ECOMMITSUCCESS=1,//All the Do-functions have done successfully. 23 ECOMMITFAILED_ROLLBACKSUCCESS,//One Do-function has done failed,but the functions had done have roll-backed successfully. 24 ECOMMITFAILED_ROLLBACKFAILED};//One Do-function has done failed,and the functions had done have roll-backed unsuccessfully. 25 26 class CTaskBase 27 { 28 public: 29 typedef boost::function<bool ()> TaskCALLBACK; 30 TaskCALLBACK m_TaskCallbackToDo; 31 TaskCALLBACK m_TaskCallbackToUndo; 32 33 bool DummyDo() 34 { 35 std::cerr<<"DummyDo"<<std::endl; 36 37 return true; 38 } 39 40 bool DummyUnDo() 41 { 42 std::cerr<<"DummyDo"<<std::endl; 43 44 return true; 45 } 46 47 virtual void SetToDo(TaskCALLBACK tcbDo) 48 { 49 m_TaskCallbackToDo=tcbDo; 50 } 51 52 virtual void SetToUndo(TaskCALLBACK tcbToUndo) 53 { 54 m_TaskCallbackToUndo=tcbToUndo; 55 } 56 57 virtual bool Do() 58 { 59 if (m_TaskCallbackToDo) 60 { 61 return m_TaskCallbackToDo(); 62 } 63 64 std::cerr<<"No Operation on Do"<<std::endl; 65 66 return true; 67 } 68 69 virtual bool Undo() 70 { 71 if (m_TaskCallbackToUndo) 72 { 73 return m_TaskCallbackToUndo(); 74 } 75 76 std::cerr<<"No Operation on Undo"<<std::endl; 77 78 return true; 79 } 80 }; 81 82 typedef CTaskBase CTransactionTask; 83 typedef CTaskBase* CTransactionTaskPtr; 84 85 class CTransactionBase 86 { 87 public: 88 virtual bool AddTask(CTransactionTask*){std::cerr << "CTransactionBase:AddTask did noting"<<std::endl;return false;} 89 virtual ETransRes CommitOrAutoRollback(){std::cerr << "CTransactionBase:CommitOrAutoRollback did noting"<<std::endl;return EDUMMY;} 90 }; 91 } 92 93 namespace TransactionbyWLS 94 { 95 class CTaskItemSample:public CTaskItemBase 96 { 97 public: 98 virtual bool Doing() 99 { 100 std::cout<<"doing:"<<m_strText<<std::endl; 101 102 return true; 103 } 104 virtual bool Undoing() 105 { 106 std::cout<<"Undoing:"<<m_strText<<std::endl; 107 108 return true; 109 } 110 111 void SetText(std::string strText) 112 { 113 m_strText=strText; 114 } 115 116 protected: 117 std::string m_strText; 118 }; 119 120 class CTaskItemSampleWithException:public CTaskItemBase 121 { 122 public: 123 virtual bool Doing() 124 { 125 std::cout<<"Doing:"<<m_strText<<std::endl; 126 127 throw std::string("hahaha"); 128 129 return true; 130 } 131 virtual bool Undoing() 132 { 133 std::cout<<"Undoing:"<<m_strText<<std::endl; 134 135 return true; 136 } 137 138 void SetText(std::string strText) 139 { 140 m_strText=strText; 141 } 142 143 protected: 144 std::string m_strText; 145 }; 146 147 class CTask:public CTaskBase 148 { 149 150 }; 151 152 class CTransaction:public CTransactionBase 153 { 154 public: 155 bool AddTask(CTransactionTask* poCmdPtr) 156 { 157 bool bAdding=true; 158 159 try 160 { 161 m_listCmdPtr.push_back(poCmdPtr); 162 } 163 catch (std::exception& e) 164 { 165 bAdding=false; 166 std::cerr << "exception caught: " << e.what() <<std::endl; 167 } 168 catch (...) 169 { 170 bAdding=false; 171 std::cerr << "Some error occurred."<<std::endl; 172 } 173 174 return bAdding; 175 } 176 177 void ClearAll() 178 { 179 m_listCmdPtr.clear(); 180 } 181 182 ETransRes CommitOrAutoRollback() 183 { 184 bool bDone=true; 185 bool bRollbackDone=false; 186 187 ITListCmdPtr it; 188 for(it=m_listCmdPtr.begin();it!=m_listCmdPtr.end();++it) 189 { 190 //Maybe we need a try...catch but not throwing anything anymore. 191 //So we need handle exceptions in the Member Function Do. 192 //if (!(bDone=(*it)->Do())) 193 //{ 194 // break; 195 //} 196 197 try 198 { 199 bDone=(*it)->Do(); 200 } 201 catch (...) 202 { 203 bDone=false; 204 std::cerr << "Some error occurred in the Commit part of CommitOrAutoRollback."<<std::endl; 205 } 206 207 if (!bDone) 208 { 209 break; 210 } 211 } 212 213 if (!bDone) 214 { 215 RITListCmdPtr rit(++it); 216 217 for (;rit!=m_listCmdPtr.rend();++rit) 218 { 219 //The same as above. 220 //if (!(bRollbackDone=(*it)->UnDo())) 221 //{ 222 // std::cout<<"Some error occurred."<<std::endl; 223 // 224 // return COMMITFAILED_ROLLBACKFAILED; 225 //} 226 227 try 228 { 229 bRollbackDone=(*rit)->Undo(); 230 } 231 catch (...) 232 { 233 bRollbackDone=false; 234 std::cerr << "Some error occurred in the AutoRollback part of CommitOrAutoRollback."<<std::endl; 235 } 236 237 if (!bRollbackDone) 238 { 239 return ECOMMITFAILED_ROLLBACKFAILED; 240 } 241 } 242 243 return ECOMMITFAILED_ROLLBACKSUCCESS; 244 } 245 246 return ECOMMITSUCCESS; 247 } 248 249 protected: 250 typedef std::list<CTransactionTask*>::iterator ITListCmdPtr; 251 typedef std::list<CTransactionTask*>::reverse_iterator RITListCmdPtr; 252 253 typedef std::list<CTransactionTask*> ListCmdPtr; 254 255 protected: 256 ListCmdPtr m_listCmdPtr; 257 }; 258 259 260 } 261 262 int main() 263 { 264 //1 265 boost::shared_ptr<TransactionbyWLS::CTaskItemSample> pTaskItem1(new TransactionbyWLS::CTaskItemSample()); 266 pTaskItem1->SetText("本博客作者:王林森(wlsandwho)"); 267 268 TransactionbyWLS::CTask oTask1; 269 oTask1.SetToDo(boost::bind(&TransactionbyWLS::CTaskItemSample::Doing,pTaskItem1)); 270 oTask1.m_TaskCallbackToUndo=boost::bind(&TransactionbyWLS::CTaskItemSample::Undoing,pTaskItem1); 271 272 //2 273 boost::shared_ptr<TransactionbyWLS::CTaskItemSample> pTaskItem2(new TransactionbyWLS::CTaskItemSample()); 274 pTaskItem2->SetText("作者的邮箱:wlsandwho@foxmail.com"); 275 276 TransactionbyWLS::CTask oTask2; 277 oTask2.SetToDo(boost::bind(&TransactionbyWLS::CTaskItemSample::Doing,pTaskItem2)); 278 oTask2.SetToUndo(boost::bind(&TransactionbyWLS::CTaskItemSample::Undoing,pTaskItem2)); 279 280 //3 281 boost::shared_ptr<TransactionbyWLS::CTaskItemSampleWithException> pTaskItem3(new TransactionbyWLS::CTaskItemSampleWithException()); 282 pTaskItem3->SetText("本博客禁止转载"); 283 284 TransactionbyWLS::CTask oTask3; 285 oTask3.SetToDo(boost::bind(&TransactionbyWLS::CTaskItemSampleWithException::Doing,pTaskItem3)); 286 oTask3.m_TaskCallbackToUndo=boost::bind(&TransactionbyWLS::CTaskItemSampleWithException::Undoing,pTaskItem3); 287 288 289 // 290 TransactionbyWLS::CTransaction oTransaction; 291 oTransaction.AddTask(&oTask1); 292 oTransaction.AddTask(&oTask2); 293 oTransaction.AddTask(&oTask3); 294 295 oTransaction.CommitOrAutoRollback(); 296 297 system("pause"); 298 299 return 0; 300 }
这个版本简要的实现了上图模型,不能用于实际生产。(实际上本系列所有代码均不能用于生产,但是你改改的话,还真不好说。)
所以很快有了第二版。
=======================================================================
第二版代码:功能上未修改
移除了Boost。能够在MFC对话框程序上跑。
1 #pragma once 2 3 #include <iostream> 4 #include <list> 5 #include <queue> 6 #include <string> 7 #include <functional> 8 9 10 // #include <boost/shared_ptr.hpp> 11 // #include <boost/enable_shared_from_this.hpp> 12 // #include <boost/bind.hpp> 13 // #include <boost/function.hpp> 14 15 16 namespace TransactionbyWLS 17 { 18 class CTaskItemBase 19 { 20 public: 21 virtual bool Doing()=0; 22 virtual bool Undoing()=0; 23 }; 24 25 ////////////////////////////////////////////////////////////////////////// 26 //As a return-value of the function CommitOrAutoRollback. 27 enum ETransRes{ EDUMMY=0,//As a virtual function's return-value Only. 28 ECOMMITSUCCESS=1,//All the Do-functions have done successfully. 29 ECOMMITFAILED_ROLLBACKSUCCESS,//One Do-function has done failed,but the functions had done have roll-backed successfully. 30 ECOMMITFAILED_ROLLBACKFAILED};//One Do-function has done failed,and the functions had done have roll-backed unsuccessfully. 31 32 class CTaskBase 33 { 34 public: 35 typedef std::function<bool ()> TaskCALLBACK; 36 37 public: 38 CTaskBase():m_TaskCallbackToDo(0),m_TaskCallbackToUndo(0){} 39 40 protected: 41 bool DummyDo() 42 { 43 std::cerr<<"DummyDo"<<std::endl; 44 45 return true; 46 } 47 48 bool DummyUnDo() 49 { 50 std::cerr<<"DummyDo"<<std::endl; 51 52 return true; 53 } 54 public: 55 virtual void SetToDo(TaskCALLBACK tcbDo) 56 { 57 m_TaskCallbackToDo=tcbDo; 58 } 59 60 virtual void SetToUndo(TaskCALLBACK tcbToUndo) 61 { 62 m_TaskCallbackToUndo=tcbToUndo; 63 } 64 65 virtual bool Do() 66 { 67 if (m_TaskCallbackToDo) 68 { 69 return m_TaskCallbackToDo(); 70 } 71 72 DummyDo(); 73 74 return true; 75 } 76 77 virtual bool Undo() 78 { 79 if (m_TaskCallbackToUndo) 80 { 81 return m_TaskCallbackToUndo(); 82 } 83 84 DummyUnDo(); 85 86 return true; 87 } 88 89 protected: 90 TaskCALLBACK m_TaskCallbackToDo; 91 TaskCALLBACK m_TaskCallbackToUndo; 92 }; 93 94 typedef CTaskBase CTransactionTask; 95 typedef CTaskBase* CTransactionTaskPtr; 96 97 // class CTaskBaseViaBoost 98 // { 99 // public: 100 // // CTaskBase():m_TaskCallbackToDo(boost::bind(&TransactionbyWLS::CTaskBase::DummyDo),_1),m_TaskCallbackToUndo(boost::bind(&TransactionbyWLS::CTaskBase::DummyUnDo),_1){} 101 // // //boost::bind(&TransactionbyWLS::CTaskItemSample::Doing,pTaskItem2) 102 // typedef boost::function<bool ()> TaskCALLBACK; 103 // TaskCALLBACK m_TaskCallbackToDo; 104 // TaskCALLBACK m_TaskCallbackToUndo; 105 // 106 // bool DummyDo() 107 // { 108 // std::cerr<<"DummyDo"<<std::endl; 109 // 110 // return true; 111 // } 112 // 113 // bool DummyUnDo() 114 // { 115 // std::cerr<<"DummyDo"<<std::endl; 116 // 117 // return true; 118 // } 119 // 120 // virtual void SetToDo(TaskCALLBACK tcbDo) 121 // { 122 // m_TaskCallbackToDo=tcbDo; 123 // } 124 // 125 // virtual void SetToUndo(TaskCALLBACK tcbToUndo) 126 // { 127 // m_TaskCallbackToUndo=tcbToUndo; 128 // } 129 // 130 // virtual bool Do() 131 // { 132 // if (m_TaskCallbackToDo) 133 // { 134 // return m_TaskCallbackToDo(); 135 // } 136 // 137 // std::cerr<<"No Operation on Do"<<std::endl; 138 // 139 // return true; 140 // } 141 // 142 // virtual bool Undo() 143 // { 144 // if (m_TaskCallbackToUndo) 145 // { 146 // return m_TaskCallbackToUndo(); 147 // } 148 // 149 // std::cerr<<"No Operation on Undo"<<std::endl; 150 // 151 // return true; 152 // } 153 // }; 154 // 155 // 156 //typedef CTaskBaseViaBoost CTransactionTask; 157 //typedef CTaskBaseViaBoost* CTransactionTaskPtr; 158 159 class CTransactionBase 160 { 161 public: 162 virtual bool AddTask(CTransactionTask*){std::cerr << "CTransactionBase:AddTask did noting"<<std::endl;return false;} 163 virtual ETransRes CommitOrAutoRollback(){std::cerr << "CTransactionBase:CommitOrAutoRollback did noting"<<std::endl;return EDUMMY;} 164 }; 165 } 166 167 namespace TransactionbyWLS 168 { 169 class CTaskItemSample:public CTaskItemBase 170 { 171 public: 172 virtual bool Doing() 173 { 174 std::cout<<"doing:"<<m_strText<<std::endl; 175 176 return true; 177 } 178 virtual bool Undoing() 179 { 180 std::cout<<"Undoing:"<<m_strText<<std::endl; 181 182 return true; 183 } 184 185 void SetText(std::string strText) 186 { 187 m_strText=strText; 188 } 189 190 protected: 191 std::string m_strText; 192 }; 193 194 class CTaskItemSampleWithException:public CTaskItemBase 195 { 196 public: 197 virtual bool Doing() 198 { 199 std::cout<<"Doing:"<<m_strText<<std::endl; 200 201 throw std::string("hahaha"); 202 203 return true; 204 } 205 virtual bool Undoing() 206 { 207 std::cout<<"Undoing:"<<m_strText<<std::endl; 208 209 return true; 210 } 211 212 void SetText(std::string strText) 213 { 214 m_strText=strText; 215 } 216 217 protected: 218 std::string m_strText; 219 }; 220 221 // class CTask:public CTaskBaseViaBoost 222 // { 223 // 224 // }; 225 226 227 class CTask:public CTaskBase 228 { 229 230 }; 231 232 class CTransaction:public CTransactionBase 233 { 234 public: 235 bool AddTask(CTransactionTask* poCmdPtr) 236 { 237 bool bAdding=true; 238 239 try 240 { 241 m_listCmdPtr.push_back(poCmdPtr); 242 } 243 catch (std::exception& e) 244 { 245 bAdding=false; 246 std::cerr << "exception caught: " << e.what() <<std::endl; 247 } 248 catch (...) 249 { 250 bAdding=false; 251 std::cerr << "Some error occurred."<<std::endl; 252 } 253 254 return bAdding; 255 } 256 257 void ClearAll() 258 { 259 m_listCmdPtr.clear(); 260 } 261 262 ETransRes CommitOrAutoRollback() 263 { 264 bool bDone=true; 265 bool bRollbackDone=false; 266 267 ITListCmdPtr it; 268 for(it=m_listCmdPtr.begin();it!=m_listCmdPtr.end();++it) 269 { 270 //Maybe we need a try...catch but not throwing anything anymore. 271 //So we need handle exceptions in the Member Function Do. 272 //if (!(bDone=(*it)->Do())) 273 //{ 274 // break; 275 //} 276 277 try 278 { 279 bDone=(*it)->Do(); 280 } 281 catch (...) 282 { 283 bDone=false; 284 std::cerr << "Some error occurred in the Commit part of CommitOrAutoRollback."<<std::endl; 285 } 286 287 if (!bDone) 288 { 289 break; 290 } 291 } 292 293 if (!bDone) 294 { 295 RITListCmdPtr rit(++it); 296 297 for (;rit!=m_listCmdPtr.rend();++rit) 298 { 299 //The same as above. 300 //if (!(bRollbackDone=(*it)->UnDo())) 301 //{ 302 // std::cout<<"Some error occurred."<<std::endl; 303 // 304 // return COMMITFAILED_ROLLBACKFAILED; 305 //} 306 307 try 308 { 309 bRollbackDone=(*rit)->Undo(); 310 } 311 catch (...) 312 { 313 bRollbackDone=false; 314 std::cerr << "Some error occurred in the AutoRollback part of CommitOrAutoRollback."<<std::endl; 315 } 316 317 if (!bRollbackDone) 318 { 319 return ECOMMITFAILED_ROLLBACKFAILED; 320 } 321 } 322 323 return ECOMMITFAILED_ROLLBACKSUCCESS; 324 } 325 326 return ECOMMITSUCCESS; 327 } 328 329 protected: 330 typedef std::list<CTransactionTask*>::iterator ITListCmdPtr; 331 typedef std::list<CTransactionTask*>::reverse_iterator RITListCmdPtr; 332 333 typedef std::list<CTransactionTask*> ListCmdPtr; 334 335 protected: 336 ListCmdPtr m_listCmdPtr; 337 }; 338 } 339 340 341 int main() 342 { 343 TransactionbyWLS::CTaskItemSample oTaskItem1; 344 oTaskItem1.SetText("本博客作者:王林森(wlsandwho)"); 345 TransactionbyWLS::CTask oTask1; 346 oTask1.SetToDo(std::bind(&TransactionbyWLS::CTaskItemSample::Doing,&oTaskItem1)); 347 oTask1.SetToUndo(std::bind(&TransactionbyWLS::CTaskItemSample::Undoing,&oTaskItem1)); 348 349 TransactionbyWLS::CTaskItemSample oTaskItem2; 350 oTaskItem2.SetText("作者的邮箱:wlsandwho@foxmail.com"); 351 TransactionbyWLS::CTask oTask2; 352 oTask2.SetToDo(std::bind(&TransactionbyWLS::CTaskItemSample::Doing,&oTaskItem2)); 353 oTask2.SetToUndo(std::bind(&TransactionbyWLS::CTaskItemSample::Undoing,&oTaskItem2)); 354 355 TransactionbyWLS::CTaskItemSampleWithException oTaskItem3; 356 oTaskItem3.SetText("本博客禁止转载"); 357 TransactionbyWLS::CTask oTask3; 358 oTask3.SetToDo(std::bind(&TransactionbyWLS::CTaskItemSampleWithException::Doing,&oTaskItem3)); 359 oTask3.SetToUndo(std::bind(&TransactionbyWLS::CTaskItemSampleWithException::Undoing,&oTaskItem3)); 360 361 TransactionbyWLS::CTransaction oTransaction; 362 oTransaction.AddTask(&oTask1); 363 oTransaction.AddTask(&oTask2); 364 oTransaction.AddTask(&oTask3); 365 366 oTransaction.CommitOrAutoRollback(); 367 368 system("pause"); 369 370 return 0; 371 }
更改的地方不大,没啥说的。当然也不能用于生产。作为小工具自己改改在小Demo里用一下倒是可以。
=======================================================================
还有很多坑,有空再填吧。键盘和桌子都好凉。(枚举值只是为了再做扩展。)
=======================================================================
因为总是有爬虫网站抓取我的博客,无视我的版权,我很伤心,所以文章最后只能这样结尾。
下面开始点名:
Asp.net教程_mvc4_C#_Ado.net_seo_Java_HTML CSS教程
www.tzwhx.com
www.th7.cn
解决方案网
帮客之家 | IT技术 建站编程 电脑教程 www.bkjia.com
软件开发,程序错误,exception
www.java123.net
一键重装系统_打造智能化重装系统软件
www.bitscn.com
http://www.admin85.com/
http://www.3fwork.com/
技术博客-最新最全的技术疑难解决博客
好库文摘 - 技术改变世界
红黑联盟:十三年IT技术门户 精英梦想由此起航 (网络安全,黑客防御,信息安全,编程,系统,网络)
以上都是侵犯我版权的爬虫网站。
=======================================================================
没什么意外的话,这会是个系列:
C++基础——模拟事务 (1)COMMAND模式
C++基础——模拟事务 (2)COMPOSITE模式
C++基础——模拟事务 (3)CHAIN OF RESPONSIBILITY模式
=======================================================================
(友情支持请扫描这个)
微信扫描上方二维码捐赠