=================================版权声明=================================
版权声明:原创文章 禁止转载
请通过右侧公告中的“联系邮箱([email protected])”联系我
勿用于学术性引用。
勿用于商业出版、商业印刷、商业引用以及其他商业用途。
本文不定期修正完善。
本文链接:http://www.cnblogs.com/wlsandwho/p/5160380.html
耻辱墙:http://www.cnblogs.com/wlsandwho/p/4206472.html
=======================================================================
因为要用到好多设计模式,所以我把原文拆成几部分,每部分讲解一个设计模式、用一个模式实现一个扩展功能。wlsandwho王林森
(这意味着还有一篇。)
=======================================================================
上一篇讲了用COMMAND模式设计事务小工具的基本骨架,传送门:C++基础——模拟事务 (1)COMMAND模式
这里将继续使用Composite模式,以使事务可以嵌套。wlsandwho王林森
=======================================================================
下面该去考虑如何实现“嵌套事务”了。wlsandwho王林森
想要一个事务像一个任务一样,被添加到另一个事务里,并且能任意的组合,形成一个树形的结构,那么事务肯定要有和任务一样的接口。
好像composite模式比较合适处理这个问题。
四人帮的典型的composite对象结构图我就不画了,composite结构图我也不画了。wlsandwho王林森
事务要想拥有任务的功能,最简单的方法是事务类继承任务类。考虑到单继承、多继承之争,我采用单继承实现。
大致结构图如下。wlsandwho王林森
如此一来,CTransactionBase有了CTaskBase的接口,就能够把一个CTransaction加到另一个CTransaction的容器里。wlsandwho王林森
回顾一下CTaskBase的两个接口函数,一个是Do,Do里执行Doing,另一个Undo,Undo里执行Undoing。Doing和Undoing是用Set函数进行手工设置绑定的。
CTransactionBase继承此接口后,Do里执行Commit,Undo里执行Rollback。Commit和Rollback是CTransactionBase的保护成员函数。这样,
把一个CTransaction加到另一个CTransaction的容器里时,不再需要额外的设置Do和Undo的动作,他们是内置的。
下面上第三版代码。wlsandwho王林森
=======================================================================
1 #include <iostream> 2 #include <list> 3 #include <string> 4 #include <functional> 5 6 namespace TransactionbyWLS 7 { 8 class CTaskItemBase 9 { 10 public: 11 virtual bool Doing()=0; 12 virtual bool Undoing()=0; 13 }; 14 15 static const int ENUM_BALENCEPOINT=1000; 16 static const int ENUM_BOUNDARYRANGE=500; 17 static const int ENUM_UPPERBOUNDARY=ENUM_BALENCEPOINT+ENUM_BOUNDARYRANGE; 18 static const int ENUM_LOWERBOUNDARY=ENUM_BALENCEPOINT-ENUM_BOUNDARYRANGE; 19 static const int ENUM_DELTA=1; 20 static const int ENUM_TRUE=1; 21 static const int ENUM_FALSE=0; 22 enum ETransRes { 23 EFALSE=ENUM_FALSE, 24 ETRUE=ENUM_TRUE, 25 26 ECOMMITSUCCESS=ENUM_BALENCEPOINT+ENUM_DELTA, 27 EDUMMY=ENUM_BALENCEPOINT,//1000,dummy. 28 ECOMMITFAILED_ROLLBACKSUCCESS=ENUM_BALENCEPOINT-ENUM_DELTA, 29 ECOMMITFAILED_ROLLBACKFAILED=ENUM_BALENCEPOINT-ENUM_DELTA*2, 30 }; 31 32 class CTaskBase 33 { 34 public: 35 typedef std::function<bool ()> TaskCALLBACK; 36 TaskCALLBACK m_TaskCallbackToDo; 37 TaskCALLBACK m_TaskCallbackToUndo; 38 39 CTaskBase():m_TaskCallbackToDo(0),m_TaskCallbackToUndo(0){} 40 41 virtual void SetToDo(TaskCALLBACK tcbDo) 42 { 43 m_TaskCallbackToDo=tcbDo; 44 } 45 46 virtual void SetToUndo(TaskCALLBACK tcbToUndo) 47 { 48 m_TaskCallbackToUndo=tcbToUndo; 49 } 50 51 virtual bool Do() 52 { 53 if (m_TaskCallbackToDo) 54 { 55 return m_TaskCallbackToDo(); 56 } 57 58 DummyDo(); 59 60 return true; 61 } 62 63 virtual bool Undo() 64 { 65 if (m_TaskCallbackToUndo) 66 { 67 return m_TaskCallbackToUndo(); 68 } 69 70 DummyUnDo(); 71 72 return true; 73 } 74 75 protected: 76 bool DummyDo() 77 { 78 std::cerr<<"DummyDo"<<std::endl; 79 80 return true; 81 } 82 83 bool DummyUnDo() 84 { 85 std::cerr<<"DummyDo"<<std::endl; 86 87 return true; 88 } 89 }; 90 91 typedef CTaskBase CTransactionTask; 92 typedef CTaskBase* CTransactionTaskPtr; 93 94 class CTransactionBase:public CTaskBase 95 { 96 public: 97 virtual bool AddTask(CTransactionTask*){std::cerr << "CTransactionBase:AddTask did noting."<<std::endl;return false;} 98 virtual ETransRes CommitOrAutoRollback(){std::cerr << "CTransactionBase:CommitOrAutoRollback did noting."<<std::endl;return EDUMMY;} 99 virtual bool Commit(){std::cerr<<"CTransactionBase:Commit did noting."<<std::endl; return true;} 100 virtual bool Rollback(){std::cerr<<"CTransactionBase:Rollback did noting."<<std::endl; return true;} 101 }; 102 } 103 104 namespace TransactionbyWLS 105 { 106 class CTaskItemSample:public CTaskItemBase 107 { 108 public: 109 virtual bool Doing() 110 { 111 std::cout<<"Doing:"<<m_strText<<std::endl; 112 113 return true; 114 } 115 virtual bool Undoing() 116 { 117 std::cout<<"Undoing:"<<m_strText<<std::endl; 118 119 return true; 120 } 121 122 void SetText(std::string strText) 123 { 124 m_strText=strText; 125 } 126 127 protected: 128 std::string m_strText; 129 }; 130 131 class CTaskItemSampleWithException:public CTaskItemBase 132 { 133 public: 134 virtual bool Doing() 135 { 136 std::cout<<"Doing:"<<m_strText<<std::endl; 137 138 throw std::string("hahaha"); 139 140 return true; 141 } 142 virtual bool Undoing() 143 { 144 std::cout<<"Undoing:"<<m_strText<<std::endl; 145 146 return true; 147 } 148 149 void SetText(std::string strText) 150 { 151 m_strText=strText; 152 } 153 154 protected: 155 std::string m_strText; 156 }; 157 158 class CTask:public CTaskBase 159 { 160 161 }; 162 163 class CTransaction:public CTransactionBase 164 { 165 protected: 166 typedef std::list<CTransactionTask*>::iterator ITListCmdPtr; 167 typedef std::list<CTransactionTask*>::reverse_iterator RITListCmdPtr; 168 169 typedef std::list<CTransactionTask*> ListCmdPtr; 170 171 public: 172 bool AddTask(CTransactionTask* poCmdPtr) 173 { 174 bool bAdding=true; 175 176 try 177 { 178 m_listCmdPtr.push_back(poCmdPtr); 179 } 180 catch (std::exception& e) 181 { 182 bAdding=false; 183 std::cerr << "exception caught: " << e.what() <<std::endl; 184 } 185 catch (...) 186 { 187 bAdding=false; 188 std::cerr << "Some error occurred."<<std::endl; 189 } 190 191 return bAdding; 192 } 193 194 void ClearAll()//no recursion 195 { 196 m_listCmdPtr.clear(); 197 } 198 199 bool Commit() 200 { 201 bool bDone=true; 202 203 for(m_itListCmdPtr=m_listCmdPtr.begin();m_itListCmdPtr!=m_listCmdPtr.end();++m_itListCmdPtr) 204 { 205 //Maybe we need a try...catch but not throwing anything anymore. 206 //So we need handle exceptions in the Member Function Do. 207 //if (!(bDone=(*it)->Do())) 208 //{ 209 // break; 210 //} 211 212 try 213 { 214 bDone=(*m_itListCmdPtr)->Do(); 215 } 216 catch (...) 217 { 218 bDone=false; 219 std::cerr << "Some error occurred in the Commit."<<std::endl; 220 } 221 222 if (!bDone) 223 { 224 return false; 225 } 226 } 227 228 return true; 229 } 230 231 bool Rollback() 232 { 233 if (m_itListCmdPtr==m_listCmdPtr.end()) 234 { 235 RITListCmdPtr rit=m_listCmdPtr.rbegin(); 236 return Traverse(rit,m_listCmdPtr); 237 } 238 else 239 { 240 RITListCmdPtr rit(++m_itListCmdPtr); 241 return Traverse(rit,m_listCmdPtr); 242 } 243 244 return false; 245 } 246 247 bool Do() 248 { 249 return Commit(); 250 } 251 252 bool Undo() 253 { 254 return Rollback(); 255 } 256 257 ETransRes CommitOrAutoRollback() 258 { 259 bool bDone=true; 260 bool bRollbackDone=false; 261 262 ITListCmdPtr it; 263 for(it=m_listCmdPtr.begin();it!=m_listCmdPtr.end();++it) 264 { 265 //Maybe we need a try...catch but not throwing anything anymore. 266 //So we need handle exceptions in the Member Function Do. 267 //if (!(bDone=(*it)->Do())) 268 //{ 269 // break; 270 //} 271 272 try 273 { 274 bDone=(*it)->Do(); 275 } 276 catch (...) 277 { 278 bDone=false; 279 std::cerr << "Some error occurred in the Commit part of CommitOrAutoRollback."<<std::endl; 280 } 281 282 if (!bDone) 283 { 284 break; 285 } 286 } 287 288 if (!bDone) 289 { 290 RITListCmdPtr rit(++it); 291 292 for (;rit!=m_listCmdPtr.rend();++rit) 293 { 294 //The same as above. 295 //if (!(bRollbackDone=(*it)->UnDo())) 296 //{ 297 // std::cout<<"Some error occurred."<<std::endl; 298 // 299 // return COMMITFAILED_ROLLBACKFAILED; 300 //} 301 302 try 303 { 304 bRollbackDone=(*rit)->Undo(); 305 } 306 catch (...) 307 { 308 bRollbackDone=false; 309 std::cerr << "Some error occurred in the AutoRollback part of CommitOrAutoRollback."<<std::endl; 310 } 311 312 if (!bRollbackDone) 313 { 314 return ECOMMITFAILED_ROLLBACKFAILED; 315 } 316 } 317 318 return ECOMMITFAILED_ROLLBACKSUCCESS; 319 } 320 321 return ECOMMITSUCCESS; 322 } 323 324 protected: 325 bool Traverse(RITListCmdPtr& rit,ListCmdPtr& list) 326 { 327 bool bRollbackDone=false; 328 329 for (;rit!=m_listCmdPtr.rend();++rit) 330 { 331 //The same as above. 332 //if (!(bRollbackDone=(*it)->UnDo())) 333 //{ 334 // std::cout<<"Some error occurred."<<std::endl; 335 // 336 // return COMMITFAILED_ROLLBACKFAILED; 337 //} 338 339 try 340 { 341 bRollbackDone=(*rit)->Undo(); 342 } 343 catch (...) 344 { 345 bRollbackDone=false; 346 std::cerr << "Some error occurred in the Rollback."<<std::endl; 347 } 348 349 if (!bRollbackDone) 350 { 351 return false; 352 } 353 } 354 355 return true; 356 } 357 358 protected: 359 ListCmdPtr m_listCmdPtr; 360 ITListCmdPtr m_itListCmdPtr; 361 }; 362 } 363 364 365 int main() 366 { 367 ////////////////////////////////////////////////////////////////////////// 368 TransactionbyWLS::CTaskItemSample oTaskItem1; 369 oTaskItem1.SetText("本博客作者:王林森(wlsandwho)"); 370 TransactionbyWLS::CTask oTask1; 371 oTask1.SetToDo(std::bind(&TransactionbyWLS::CTaskItemSample::Doing,&oTaskItem1)); 372 oTask1.m_TaskCallbackToUndo=std::bind(&TransactionbyWLS::CTaskItemSample::Undoing,&oTaskItem1); 373 374 TransactionbyWLS::CTaskItemSample oTaskItem2; 375 oTaskItem2.SetText("作者的邮箱:[email protected]"); 376 TransactionbyWLS::CTask oTask2; 377 oTask2.SetToDo(std::bind(&TransactionbyWLS::CTaskItemSample::Doing,&oTaskItem2)); 378 oTask2.m_TaskCallbackToUndo=std::bind(&TransactionbyWLS::CTaskItemSample::Undoing,&oTaskItem2); 379 380 // TransactionbyWLS::CTaskItemSampleWithException oTaskItem3; 381 // oTaskItem3.SetText("本博客禁止转载"); 382 // TransactionbyWLS::CTask oTask3; 383 // oTask3.SetToDo(std::bind(&TransactionbyWLS::CTaskItemSampleWithException::Doing,&oTaskItem3)); 384 // oTask3.m_TaskCallbackToUndo=std::bind(&TransactionbyWLS::CTaskItemSampleWithException::Undoing,&oTaskItem3); 385 TransactionbyWLS::CTaskItemSample oTaskItem3; 386 oTaskItem3.SetText("本博客禁止转载"); 387 TransactionbyWLS::CTask oTask3; 388 oTask3.SetToDo(std::bind(&TransactionbyWLS::CTaskItemSample::Doing,&oTaskItem3)); 389 oTask3.m_TaskCallbackToUndo=std::bind(&TransactionbyWLS::CTaskItemSample::Undoing,&oTaskItem3); 390 391 TransactionbyWLS::CTransaction oTransaction1; 392 oTransaction1.AddTask(&oTask1); 393 oTransaction1.AddTask(&oTask2); 394 oTransaction1.AddTask(&oTask3); 395 //oTransaction1.CommitOrAutoRollback(); 396 397 ////////////////////////////////////////////////////////////////////////// 398 TransactionbyWLS::CTaskItemSample oTaskItem4; 399 oTaskItem4.SetText("保留一切权利"); 400 TransactionbyWLS::CTask oTask4; 401 oTask4.SetToDo(std::bind(&TransactionbyWLS::CTaskItemSample::Doing,&oTaskItem4)); 402 oTask4.m_TaskCallbackToUndo=std::bind(&TransactionbyWLS::CTaskItemSample::Undoing,&oTaskItem4); 403 404 TransactionbyWLS::CTaskItemSampleWithException oTaskItem5; 405 oTaskItem5.SetText("文章内容不定期修订 务必阅读原文http://www.cnblogs.com/wlsandwho/p/5160380.html"); 406 TransactionbyWLS::CTask oTask5; 407 oTask5.SetToDo(std::bind(&TransactionbyWLS::CTaskItemSampleWithException::Doing,&oTaskItem5)); 408 oTask5.m_TaskCallbackToUndo=std::bind(&TransactionbyWLS::CTaskItemSampleWithException::Undoing,&oTaskItem5); 409 410 // TransactionbyWLS::CTaskItemSample oTaskItem5; 411 // oTaskItem5.SetText("文章内容不定期修订 务必阅读原文http://www.cnblogs.com/wlsandwho/p/5160380.html"); 412 // TransactionbyWLS::CTask oTask5; 413 // oTask5.SetToDo(std::bind(&TransactionbyWLS::CTaskItemSample::Doing,&oTaskItem5)); 414 // oTask5.m_TaskCallbackToUndo=std::bind(&TransactionbyWLS::CTaskItemSample::Undoing,&oTaskItem5); 415 416 TransactionbyWLS::CTransaction oTransaction2; 417 oTransaction2.AddTask(&oTask4); 418 oTransaction2.AddTask(&oTask5); 419 //oTransaction2.CommitOrAutoRollback(); 420 421 422 ////////////////////////////////////////////////////////////////////////// 423 TransactionbyWLS::CTransaction oTransaction3; 424 oTransaction3.AddTask(&oTransaction1); 425 oTransaction3.AddTask(&oTransaction2); 426 oTransaction3.CommitOrAutoRollback(); 427 428 system("pause"); 429 430 return 0; 431 }
=======================================================================
还有很多坑,有空再填吧。键盘和桌子都好凉。(枚举值只是为了再做扩展。)
=======================================================================
因为总是有爬虫网站抓取我的博客,无视我的版权,我很伤心,所以文章最后只能这样结尾。
下面开始点名:
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技术门户 精英梦想由此起航 (网络安全,黑客防御,信息安全,编程,系统,网络)
以上都是侵犯我版权的爬虫网站。
=======================================================================
没什么意外的话,这会是个系列:wlsandwho王林森
=======================================================================
20160127
好消息,事务保存点功能实现啦!
上方第三个链接就是呢!
=======================================================================
(友情支持请扫描这个)
微信扫描上方二维码捐赠