• (原创)日志处理(修改)


    日志处理

    日志可能有多种形式,比如以文件存储,显示到控制台屏幕上,或者在程序的一个列表框中……我们可以定义一个日志基类,然后继承之,针对不同的情况设计不同的子类。但如果程序中要求既在程序列表里显示日志,又要记录到文件或者还要记录到数据库等等吧,那么写日志的代码就非常麻烦,要几个日志类重复同样的动作。

    利用下面的思路可以解决这个问题,在代码中只需要一个类的一个方法,就可以搞定所有日志类写日志的动作,同时又能起到一定的注释作用,是不是非常好!

    OK! Let's go!

    首先,定义一个日志类接口,主要给不同情况下生成日志的时候用。比如有的程序在自己的界面列表上输出日志,那么就可以实现这个接口,然后把实现的类传递到CLogHelper对象中,CLogHelper负责用日志接口列表中的日志接口写日志操作,而实现ILog接口的类负责实现日志的真实写入操作。

     

    以下(核心)代码在VC6下编译并测试通过。代码中使用了STL技术。下同。

    MyInterface ILog  
    {
    public:
        ILog();
        
    virtual ~ILog();

        
    virtual void write(string logMsg);
        
    virtual void writeLn(string logMsg);

        
    void debugWrite(string logMsg);
        
    void debugWriteLn(string logMsg);
    };

      

    MyInterface 是自己定义的一个接口,按照园子里的方法如下:

    #define MyInterface class __declspec(novtable)

     

    CLogHelper类是日志类的助手,可以添加日志对象(ILog类型),提供每个日志对象的写日志功能。它也可以继承ILog接口。

    class CLogHelper : public ILog  
    {
    public:
        CLogHelper();
        
    virtual ~CLogHelper();

        
    void write(string logMsg);
        
    void writeLn(string logMsg);

        
    // 下面的方法用于DEBUG环境
        void debugWrite(string logMsg);
        
    void debugWriteLn(string logMsg);
        
        
    void add(ILog *log);
        
    private:
        list
    <ILog *> logs;
    };


    CLogHelper::CLogHelper()
    {

    }

    CLogHelper::
    ~CLogHelper()
    {
        logs.clear();
    }

    void CLogHelper::write(string logMsg)
    {
        list
    <ILog *>::iterator logi;
        
    for(logi=logs.begin();logi!=logs.end();logi++)
            (
    *logi)->write(logMsg);
    }

    void CLogHelper::writeLn(string logMsg)
    {
        
    string msg=logMsg+"\n";
        write(msg);
    }

    void CLogHelper::add(ILog *log)
    {
        logs.push_back(log);
    }

    void CLogHelper::debugWrite(string logMsg)
    {
    #ifdef _DEBUG
        write(logMsg);
    #endif
    }

    void CLogHelper::debugWriteLn(string logMsg)
    {
        
    string msg=logMsg+"\n";
        debugWrite(msg);
    }

      

    下面是具体的日志类,它们都继承ILog接口。包括写入文件的日志类,控制台显示的日志类、程序列表中用到的日志类等等。

    比如定义写入文件的日志类CLog继承ILog接口,代码略。

     

    然后提供一个Log构建器(CLogBuilder),里面包括所有的具体日志类,在构造函数里把具体的日志类添加到CLogHelper中。构造函数提供一个文件路径的参数,表示文件日志要写到什么地方。这个参数默认为mylog.log文件,表示写到程序所在目录下,文件名默认为"mylog.log"。构造函数提供另一个参数为CLogHelper,就是说CLogHelper类是从外部传入的。

    class CLogBuilder  
    {
    public:
        CLogBuilder(CLogHelper 
    *logHelper,string path="mylog.log");
        
    virtual ~CLogBuilder();

        
    string m_Path;
        
        CLog 
    *fileLog;
    };


    CLogBuilder::CLogBuilder(CLogHelper 
    *logHelper,string path)
    :fileLog(
    0),m_Path(path)
    {
        fileLog
    =new CLog(m_Path.c_str());
        
        
    // 向LogHelper中添加日志类
        logHelper->add((ILog *)fileLog);
    }

    CLogBuilder::
    ~CLogBuilder()
    {
        
    if(fileLog)
        {
            delete(fileLog);
            fileLog
    =NULL;
        }
    }

      

    然后定义一个职责转义类,在其它的类中需要提供写日志的时候,用这个类(定名为CRemark)。如果每个类的每个方法里都有写日志的代码,会把代码搞的很混乱,不突出方法的主题,也好像这个方法完成多项任务似的,代码不简明。记得VC的注释代码中有“// todo :”,所以这个类提供一个方法叫toDo(),其参数就是toDO()语句以下代码所完成工作的内容描述。看起来,这个方法好像是在给代码作注释。这样既起到了注释的作用,同时在toDo()方法中还可以调用日志类去写日志,岂不是一举两得。因为这个类在代码中看只是起到注释的作用,而在它的方法中却转义成了写日志,所以称其为职责转义类。当然,如果你发现这个类还可以干其它的事情,请你一定告诉我。

    class CRemark  
    {
    public:
        CRemark();
        
    virtual ~CRemark();

        CLogHelper 
    *logHelper;
        CLogBuilder 
    *logBuilder;
        
        
    void toDo(string comment,BOOL isDebug=FALSE);
    };


    CRemark::CRemark()
    :logHelper(
    0),logBuilder(0)
    {
        logHelper
    =new CLogHelper();
        logBuilder
    =new CLogBuilder(logHelper);
    }

    CRemark::
    ~CRemark()
    {
        
    if(logHelper)
        {
            delete(logHelper);
            logHelper
    =NULL;
        }
        
    if(logBuilder)
        {
            delete(logBuilder);
            logBuilder
    =NULL;
        }
    }

    void CRemark::toDo(string comment,BOOL isDebug)
    {
        
    if(isDebug)
            logHelper
    ->debugWriteLn(comment);
        
    else
            logHelper
    ->writeLn(comment);
    }

      

    代码比较完美和优雅了,就像C#那样,嘻嘻!

    可以这样使用:

    int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
    {
        CRemark mark;
        mark.toDo(
    "嘻嘻哈哈吼吼!");
      //这里是程序中实际的代码

        mark.toDo(
    "DEBUG版本显示。。。",TRUE);
      //这里是程序中实际的代码

        mark.toDo(
    "GOOD JOB!");
      //这里是程序中实际的代码

        system(
    "pause");

    }


    程序会在所在目录下创建(默认)mylog.log文件,并在其中显示三行文本;如果改成Release,则只输出两行文本。

  • 相关阅读:
    js动态绑定class(当前父级div下的子元素有没有这个class,有的话移除,没有的话添加)
    css 最简单的淡出淡出
    vue中注册全局组件并使用
    vue 安装完less之后报 Module build failed: TypeError: loaderContext.getResolve is not a function
    vue moment时间戳转日期的使用
    vue +element实现点击左侧栏目切换路由
    vue使用模板快速创建vue文件
    vue项目中全局使用vuex并注册全局属性
    npm ERR! A complete log of this run can be found in: npm ERR! D: ode ode_cache\_logs2020-06-13T08_12_35_648Z-debug.log
    cnpm的安装(超级详细版)
  • 原文地址:https://www.cnblogs.com/yxsylyh/p/loghandling.html
Copyright © 2020-2023  润新知