=================================版权声明=================================

版权声明:原创文章 禁止转载 

请通过右侧公告中的“联系邮箱(wlsandwho@foxmail.com)”联系我

勿用于学术性引用。

勿用于商业出版、商业印刷、商业引用以及其他商业用途。                   

 

本文不定期修正完善。

本文链接: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("作者的邮箱:wlsandwho@foxmail.com");
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

 

C++基础——模拟事务 (1)COMMAND模式

C++基础——模拟事务 (2)COMPOSITE模式

C++基础——模拟事务 (3)CHAIN OF RESPONSIBILITY模式

=======================================================================

20160127

好消息,事务保存点功能实现啦!

上方第三个链接就是呢!

=======================================================================

(友情支持请扫描这个)

微信扫描上方二维码捐赠