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

 
装饰模式(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);
      };

       wg xLogDecorator::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 中有用到这个参数。
     3 wgxLogMsg 只封装了 string ,可以考虑封装要输出的内存。
     4 、可以把任意要输出的类型转化成 wgxLogMsg 进行输出(具体参考实际实用);
     5 、输出日志信息之前可以对要输出的信息进行压缩、加密等操作,只要被要相应的 decorator 即可。
          需要完整源码的请留下e-mail
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值