装饰模式(Decorator pattern)应用----日志信息输出

原创 2006年06月05日 21:26:00
 
装饰模式(Decorator pattern)应用----日志信息输出
    装饰模式解释:装饰模式可以动态地给一个对象添加一些额外的职责,而不用修改已有的类(设计模式—可复用面向对象软件的基础(P115))。
    在软件的开始过程中,经常需要记录一下日志信息。日志信息一般都是一些调试信息、出错信息或者程序的执行流程输出。
    日志信息有各种不同的输出方式:如输出到文件,输出到控制台,输出到数据库,输出到 Output 窗口(VC中),或者它们之间的任意组合(既要输出到文件又要输出到控制台等)等等。
    日志信息在输出之间可能要做一些处理:如对日志信息进行压缩存储,对日志信息进行加密存储,诸如此类。
日志信息可能要根据不同的严重级别或者不同的分类进行选择性的输出。如比较严重的出错可能要求在任何情况下都要输出,有的日志信息可能只作为诊断之用,在要诊断的时才要求输出。
    上述各每一项都可以改变,如增加输出方式,增加压缩方式等。
    采用装饰模式(Decorator pattern)可以实现这个需求。
    一、类的组织结构图
    类的组织结构图如下图所示:

 

    二、各个类说明:
    wgxLogInterface :定义 log 各接口
    wgxLog          :被修饰的 log 对象
    wgxLogDecorator :用来修饰对象接口
    wgxFileLog      :把 log 输出到文件
    wgxConsoleLog   :把 log 输出到控制台
    wgxFilterLog    :对输出的 log 进行过滤操作,不符合条件的 log 不输出
    wgxLogMsg       :要输出的 log 信息

     三、具体实现:
    创建一个 LogLib 工程,专门用于日志信息的输出,别的工程要用到日志信息输出时,只要链接 LogLib 可。

     1、类 wgxLogMsg
    class wgxLogMsg
         {
          private:
                  string m_strMsg; // 要输出的日志内容
          public:
                  wgxLogMsg(const char *pszMsg);
                  const char *GetMsg() const { return m_strMsg.c_str(); }
         };
 
        wgxLogMsg::wgxLogMsg(const char *pszMsg)
        {
               m_strMsg = pszMsg;
        }

 
    2、类 wgxLogInterface
    class wgxLogInterface
       {
        public:
             virtual void Log(int nPassport, const wgxLogMsg &msg) = 0;
       };
 
    3、类 wgxLog
    class wgxLog : public wgxLogInterface
       {
        public:
                void Log(int nPassport, const wgxLogMsg &msg);
        };
 
         void wgxLog::Log(int nPassport, const wgxLogMsg &msg)
       {
       }

       4、wgxLogDecorator
        class wgxLogDecorator : public wgxLogInterface
      {
       protected:
               wgxLogInterface *m_pLog;
       public:
               wgxLogDecorator(wgxLogInterface *pLog);
               virtual void Log(int nPassport, const wgxLogMsg &msg);
      };

       wgxLogDecorator::wgxLogDecorator(wgxLogInterface *pLog) : m_pLog(pLog)
      {
      }
 
       void wgxLogDecorator::Log(int nPassport, const wgxLogMsg &msg)
      {
             m_pLog->Log(nPassport, msg);
      }
 
       5、类 wgxFileLog
        class wgxFileLog : public wgxLogDecorator
      {
       private:
                string m_strLogFile; // 接受日志信息的文件名 
      public:
               wgxFileLog(wgxLogInterface *pLog, const char *pszFileName);
               void Log(int nPassport, const wgxLogMsg &msg);
      };
 
       wgxFileLog::wgxFileLog(wgxLogInterface *pLog, const char *pszFileName) : wgxLogDecorator(pLog)
      {
              m_strLogFile = pszFileName;
        }

       void wgxFileLog::Log(int nPassport, const wgxLogMsg &msg)
      {
             FILE *pf = fopen(m_strLogFile.c_str(), "a");
            if (pf)
           {
                    // 输出日志信息到文件中
                  fprintf(pf, "%s", msg.GetMsg());
                 fclose(pf);
                 return;
          }
          wgxLogDecorator::Log(nPassport, msg);
       }
 
        6、类 wgxConsloeLog
       class wgxConsoleLog : public wgxLogDecorator
       {
        public:
               wgxConsoleLog(wgxLogInterface *pLog);
              void Log(int nPassport, const wgxLogMsg &msg);
        };
        wgxConsoleLog::wgxConsoleLog(wgxLogInterface *pLog) : wgxLogDecorator(pLog)
       {
       }
 
      void wgxConsoleLog::Log(int nPassport, const wgxLogMsg &msg)
      {
            // 输出到控制台
           cout<<msg.GetMsg();
          wgxLogDecorator::Log(nPassport, msg);
       }

 
       7、类 wgxFilterLog
         const int PASSPORT_MAX = 0xff; // 最多记录 0xff 个通行证号 
          class wgxFilterLog : public wgxLogDecorator
         {
          private:
                  int m_nPassport[PASSPORT_MAX]; // 可以通过的通行证(0表示此位置上没有记录通行证号)
         public:
                 wgxFilterLog(wgxLogInterface *pLog);
                 void Log(int nPassport, const wgxLogMsg &msg);
    
                 // 注册通行证
                void RegisterPassport(int nPassport);
               // 注销通行证
               void UnregisterPassport(int nPassport);
          protected:
                  // 通行证是否可以通过
                  bool CanPass(int nPassport);
                 // 查找通行证所在的位置
                 int FindPassport(int nPassport); 
                 // 找一个空位置
                 int FindFreePos();
          };
          wgxFilterLog::wgxFilterLog(wgxLogInterface *pLog) : wgxLogDecorator(pLog)
          {
                    memset(m_nPassport, 0, sizeof (m_nPassport));
          }
           void wgxFilterLog::Log(int nPassport, const wgxLogMsg &msg)
          {
                 if (! CanPass(nPassport))
                         // 此通行证号不能通过
                        return; 
                  wgxLogDecorator::Log(nPassport, msg);
        }
 
         void wgxFilterLog::RegisterPassport(int nPassport)
        {
                   int nPos = FindPassport(nPassport);
                  if (nPos != PASSPORT_MAX)
                           // 已经注册过,不需要再注册
                           return; 
                  nPos = FindFreePos();
                  if (nPos == PASSPORT_MAX)
                          // 已经没有空位置可以存放另外的通行证
                         return;

                m_nPassport[nPos] = nPassport;
          }

             void wgxFilterLog::UnregisterPassport(int nPassport)
          {
                  int nPos = FindPassport(nPassport);
                  if (nPos == PASSPORT_MAX)
                           // 此通行证没注册过
                           return;
                 // 注销通行证
               m_nPassport[nPos] = 0;
          }
 
         bool wgxFilterLog::CanPass(int nPassport)
        {
                 return FindPassport(nPassport) != PASSPORT_MAX;
        }
 
          int wgxFilterLog::FindPassport(int nPassport)
         {
                int i = 0;
                for (; i < PASSPORT_MAX; i++)
                      if (m_nPassport[i] == nPassport)
                             // 找到通行证所在的位置
                            break;
              return i;
        }
 
        int wgxFilterLog::FindFreePos()
      {
            return FindPassport(0);
       }
 
        四、实际应用:
        #include "../LogLib/FileLog.h"
        #include "../LogLib/ConsoleLog.h"
        #include "../LogLib/Log.h"
        #include "../LogLib/FilterLog.h"
        #include "../LogLib/LogMsg.h"
        #include <map>
        #include <string>
        using namespace std;

         // 自定义 map
         class wgxMap
        {
        public:
                map<string, string> m_Map;
 
                // 自定义 map 转化为 wgxLogMsg
                operator wgxLogMsg()
              {
               #define INI_MAP(str) m_Map[str] = str;
                        INI_MAP("1");
                        INI_MAP("2");
                        INI_MAP("3");
                        INI_MAP("4");
                        INI_MAP("5");
 
                      // 输出测试代码
                       string str = "";
                       for (map<string, string>::iterator iter = m_Map.begin(); iter != m_Map.end(); iter++)
                      {
                               str += (*iter).first;
                               str += "=";
                               str += (*iter).second;
                               str += "/n";
                     }
                     return wgxLogMsg(str.c_str());
              }
        };

 
        int _tmain(int argc, _TCHAR* argv[])
       {
              // 对日志信息输出进行装饰
              wgxLog                *pLogger           = new wgxLog;
              wgxFileLog          *pFileLog1       = new wgxFileLog(pLogger, "d:/log1.txt");        // 输出到 d:/log1.txt
              wgxFileLog          *pFileLog2       = new wgxFileLog(pFileLog1, "d:/log2.txt");     // 输出到 d:/log2.txt
              wgxConsoleLog   *pConsoleLog  = new wgxConsoleLog(pFileLog2);                   // 输出到控制台
              wgxFilterLog       *pFilterLog      = new wgxFilterLog(pConsoleLog);                   // 输出过滤操作
               // 输出测试
               wgxMap mapping;
               pFilterLog->RegisterPassport(1);       // 注册通行证号1
               pFilterLog->Log(1, mapping);            // 输出 map
               pFilterLog->Log(1, "²âÊÔ´úÂë/n");   // 输出字符串

               // 删除装饰
               delete pFilterLog;
               delete pConsoleLog;
               delete pFileLog2;
               delete pFileLog1;
               delete pLogger;
              getchar();
              return 0;
       }

         五、相关说明:
     1、所有的 wgxLogDecorator 都用来修饰 wgxLog,但是 wgxLog 本身并没有做任何操作;
     2、输出 log 的接口函数 Log 都带有一个参数 nPassport 是为了过滤之用,目前仅在 wgxFilterLog 中有用到这个参数。
     3wgxLogMsg 只封装了 string,可以考虑封装要输出的内存。
     4、可以把任意要输出的类型转化成 wgxLogMsg 进行输出(具体参考实际实用);
     5、输出日志信息之前可以对要输出的信息进行压缩、加密等操作,只要被要相应的 decorator 即可。
          需要完整源码的请留下e-mail

装饰模式【Decorator Pattern】

Ladies and gentlemen,May I get your attention,Please?,Now I’m going to talk about decoratorpattern.装...

第9章 装饰模式(Decorator Pattern)

装饰模式(Decorator Pattern) ——.NET设计模式系列之十 Terrylee,2006年3月 概述 在软件系统中,有时候我们会使用继承来扩展对象的功能,但是由于继承为类型引入...

装饰模式(Decorator Pattern)

动态或者静态地为一个对象附加一个职责或者功能,称为装饰模式。它是属于结构设计模式之一,比较常用。      使用场合和优势:  为子类提供了一个可选项。 在不影响其它对象的前提下,给一个对象添加一...

理解装饰模式(decorator pattern)两个小例子

装饰、包装,重点是方法返回的不是返回值而是一个对象。当然laravel的比这复杂,这里只是小例子(个人愚见)。装饰模式是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个...

装饰模式【Decorator Pattern 】

博客地址  http://blog.csdn.net/ftx2540993425   下面横线以上内容是借鉴别人的,为了表达对作者的敬意,不做不恰当的修改,我个人的总结在后面。好的东西 ...

装饰模式--Decorator pattern

定义:动态地给一个对象增加其他职责,就增加对象的功能来说,装饰模式比生成子类实现更为灵活。 UML图如下:   Code: 抽象构件(Component)角色:...
  • jtlyuan
  • jtlyuan
  • 2012年01月07日 13:49
  • 269

装饰模式-Decorator Pattern

基本概念 装饰模式,动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比使用子类继承父类更为灵活,装饰模式可以有效地把类的核心职责和附加功能区分开。 结构图   上图摘自《大话设计模...

装饰模式(Decorator Pattern)

生活中的装饰是很好理解的,我们打两个比方。先还是说房子的装修(我不是故意的),装修无非就是要在墙上刷上粉贴上壁纸挂上饰物,让房屋显得更加雅致美观。但墙还是那堵墙,本质不会改变,只是多了一层包装而已。再...

JAVA设计模式之 装饰模式【Decorator Pattern】

一、概述 动态地给一个对象增加一些额外的职责,就增加对象功能来说,装饰模式比生成子类实现更为灵活。装饰模式是一种对象结构型模式。装饰模式是一种用于替代继承的技术,使用对象之间的关联关系取代类之间的继...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:装饰模式(Decorator pattern)应用----日志信息输出
举报原因:
原因补充:

(最多只允许输入30个字)