首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >C++11测井体系结构

C++11测井体系结构
EN

Code Review用户
提问于 2014-04-06 21:00:25
回答 1查看 2K关注 0票数 7

为了为更大的应用程序创建日志系统,我提出了以下草案。日志接收器尚未详细说明,但用于创建记录器的工厂方法和记录器本身的粗略草案是。这是一个好的开始,值得继续下去吗?或者你能看到陷阱?

代码语言:javascript
运行
复制
class LoggingSink; // abstract base class
class ConsoleSink : public LoggingSink; // some concrete logging sink
class LogfileSink : public LoggingSink; // ... too

/***********************************************/
class Logger {
public:
    void log(const std::string& msg) {
        for (LoggingSink ls : Sinks)
            ls.log(msg);
    }

private:
    std::list<std::reference_wrapper<LoggingSink>> Sinks;
    friend class LoggerFactory;
};


/***********************************************/
class LoggerFactory {
public:
    std::unique_ptr<Logger> create() {
        std::unique_ptr<Logger> result = std::make_unique<Logger>();
        result->Sinks.assign(StandardAssignedSinks.begin(), StandardAssignedSinks.end());
        return result;
    }

    void addStandardSink(LoggingSink& ls) {
        Sinks.push_back(std::reference_wrapper<LoggingSink>(ls));
    }

private:
    std::list<std::reference_wrapper<LoggingSink>> StandardAssignedSinks;
};

/***********************************************/
int main() {
    ConsoleSink cs;
    LogfileSink lfs("mylogfile.txt");

    LoggerFactory lf;
    lf.addStandardSink(cs);  // adding as reference for polymorphism
    lf.addStandardSink(lfs); // perhaps the addition of some standard sinks should be done in the constructor of LoggerFactory???

    std::unique_ptr<Logger> myLogger = lf.create();

    myLogger->log("Hello Log, I'm going to be injected soon!");
    MyClass myClassInstance(myLogger); // constructor dependency injection

    MyClass myOtherInstance(lf.create()); // direct DI
}

我也不确定朋友班的事。这是我从来不喜欢的工厂。有什么好办法吗?

EN

回答 1

Code Review用户

发布于 2014-04-07 16:01:50

正如评论中指出的那样:

我会让工厂保留所有权:

代码语言:javascript
运行
复制
class LoggerFactory {

typedef std::map<std::string, std::unique_ptr<Logger>>  Container;
typedef Container::iterator                             iterator;
typedef Container::const_iterator                       const_iterator;
typedef Container::value_type                           value_type;

typedef std::list<std::reference_wrapper<LoggingSink>>  SinkHolder;

public:
    Logger& get(std::string const& loggerName = "default")
    {
        iterator find = cont.find(loggerName);
        if (find == cont.end())
        {

            std::unique_ptr<Logger> result = std::make_unique<Logger>();

            // Personally I would not do this.
            // I would pass the iterators to the constructor
            // of the Logger object.
            result->Sinks.assign(std::begin(standardAssignedSinks),
                                 std::end(standardAssignedSinks));

            auto insertR = cont.insert(value_type(loggerName, result));
            if (!insertR.second)
            {    throw std::runtime_error("Insertion Failed");
            }
            find = insertR.first;           
        }
        return *(find->second);
    }

    void addStandardSink(LoggingSink& ls) {
        standardAssignedSinks.empace_back(ls);
    }

private:
    SinkHolder standardAssignedSinks;
    Container  cont;
};

现在你可以有多个记录器了。但是您可以重用记录器(因为每个记录器都有自己的名称)。大多数情况下,人们应该使用默认的记录器。

构建流日志记录程序并不困难,它只是需要一个中间缓冲区对象来积累消息。当它被销毁时,它会向记录器发送消息。

代码语言:javascript
运行
复制
class Logger {
    public:
        template<typename T>
        LogStreamBuffer  operator<<(T const& data) // Member so left hand side  implied as Logger
        {
            // This is not perfect
            // This may cause a copy (and thus a destruction)
            // If there is a copy/destruction cycle an extra message will be
            // sent. You can code around this problem.
            // This is just to get you started.

            return LogStreamBuffer(*this) << data;
        }
    // OTHER STUFF
};
class LogStreamBuffer
{
    Logger&            parent;
    std::stringstream  buffer;

    public:
        LogStreamBuffer(Logger& parent)
           : parent()
        {}
        ~LogStreamBuffer()
        {
            // When the object is destroyed.
            // Log the accumulated message with the parent.
            parent.log(buffer.str());
        }
        template<typename T>
        LogStreamBuffer&  operator<<(T const& data)
        {
            // Anything you log is just appended to the message.
            buffer << data;
            return *this;   // return a reference to yourself.
                            // So you can chain messages.
        }
};

// Usage:
int main()
{
     LoggerFactory   factory;
     Logger          logger = factory.get("MyLogger");


     logger << "This is a test: " << 1 << " Got it";
       //   ^^^
       //   Creates a LogStreamBuffer
       //   As an invisable temporary object.
       //   The subsequent `operator<<` will accumulate
       //   data in the buffer. When the statement is
       //   finished (at the ;) all temporaies will be
       //   destroyed. This calls the LogStreamBuffer
       //   destructor and logs your data to the Logger
       //   object. 

}
票数 3
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/46499

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档