装饰模式(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)两个小例子

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

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

一、概述 动态地给一个对象增加一些额外的职责,就增加对象功能来说,装饰模式比生成子类实现更为灵活。装饰模式是一种对象结构型模式。装饰模式是一种用于替代继承的技术,使用对象之间的关联关系取代类之间的继...
  • l416112167
  • l416112167
  • 2015年03月09日 21:07
  • 2057

设计模式——装饰模式(Decorator)

要想正确理解设计模式,首先必须明确它是为了解决什么问题而提出来的。 设计模式学习笔记 ——Shulin 转载请注明出处:http://blog.csdn.net/zhshulin 1、概念 ...
  • u012909091
  • u012909091
  • 2014年08月18日 20:23
  • 18571

设计模式总结之Decorator Pattern(装饰者模式)

装饰模式是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。...
  • cooldragon
  • cooldragon
  • 2016年08月11日 00:49
  • 1594

Android设计模式之一个例子让你彻底明白装饰者模式(Decorator Pattern)

导读这篇文章中我不会使用概念性文字来说明装饰者模式,因为通常概念性的问题都很抽象,很难懂,使得读者很难明白到底为什么要使用这种设计模式,我们设计模式的诞生,肯定是前辈们在设计程序的时候遇到了某种困难,...
  • nugongahou110
  • nugongahou110
  • 2015年12月27日 19:40
  • 2969

设计模式之八 --- 装饰模式(Decorator)

【1】基本概念           装饰模式(Decorator),动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活。 【2】简单分析           我们先来...
  • cjjky
  • cjjky
  • 2012年04月19日 20:12
  • 14360

iOS 设计模式之装饰模式(Decorator)

给一个人穿上衣服,使用装饰者模式给一个人穿上衣服,首先要定义一个 Person 类。 Person 有一个 name,还可以展示自己穿了什么。//Person.h @interface Perso...
  • a12a33
  • a12a33
  • 2016年02月17日 13:38
  • 947

浅谈JAVA设计模式之——装饰模式(Decorator)

一、概述 动态地给一个对象添加一些额外的职责。就增加功能来说,Decorator模式相比生成子类更为灵活。 二、适用性 1.在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。 2.处...
  • l1028386804
  • l1028386804
  • 2015年05月03日 23:56
  • 2050

c++设计模式----Decorator(装饰)

装饰模式: 意图: 动态地给一个对象添加一些额外的职责。就增加功能来说,Decorator 模式相比生成子类更为灵活。  适用性:            在不影响其他对象的情况下,以动态、...
  • chenxun2009
  • chenxun2009
  • 2015年09月17日 23:12
  • 673

设计模式-装饰者模式(Decorator)理解和在Android中的应用

介绍最近写代码没有手感,就看看书找点写代码的灵感。看点高大上的设计模式谈谈自己的理解。我读的是《研磨设计模式》看完之后真正的醍醐灌顶。借用一句话 一本值得反复研读的书 读了设计模式,其实我觉得看...
  • Card361401376
  • Card361401376
  • 2016年04月22日 18:22
  • 5093
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:装饰模式(Decorator pattern)应用----日志信息输出
举报原因:
原因补充:

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