在阅读了一篇关于基于策略的设计的文章并想自己尝试一些东西之后,我花了一些时间将我曾经做过的一个记录器类重新设计为基于策略的方法。
一些代码:
template <class Filter, class Formatter, class Outputter>
class LoggerImpl : public LoggerBase {
public:
LoggerImpl(const Filter& filter = Filter(), const Formatter& formatter = Formatter(), const Outputter& outputter = Outputter());
~LoggerImpl();
void log(int channel, int loglevel, const char* msg, va_list list) const;
private:
const Filter mFilter;
const Formatter mFormatter;
const Outputter mOutputter;
};
template <class Filter, class Formatter, class Outputter>
LoggerImpl<Filter, Formatter, Outputter>::LoggerImpl(const Filter& filter, const Formatter& formatter, const Outputter& outputter) :
mFilter(filter), mFormatter(formatter), mOutputter(outputter) {
debuglib::logdispatch::LoggerMgr.addLogger(this);
}
typedef LoggerImpl<NoFilter, SimpleFormatter, ConsoleOutputter> ConsoleLogger;
typedef LoggerImpl<ChannelFilter, SimpleFormatter, VSOutputter> SimpleChannelVSLogger;
typedef LoggerImpl<NoFilter, SimpleFormatter, FileOutputter> FileLogger;
ConsoleLogger c;
SimpleChannelVSLogger a(const ChannelFilter(1));
FileLogger f(NoFilter(), SimpleFormatter(), FileOutputter("log.txt"));
// macro for sending log message to all current created loggers
LOG(1, WARN, "Test %d", 1423);
根据记录器,我需要传递其他信息,例如 SimpleChannelVsLogger 中的日志通道或 FileOututter 中的日志文件的文件名。
我将参数作为常量引用传递给 LoggerImpl 的构造函数,然后将它们复制到存储在记录器类中的对象中。需要复制它们,因为生命周期扩展不能通过函数参数传递,该函数参数在将临时创建的对象绑定到 const 引用时发生(更多信息请参见:Does a const reference prolong the life of a temporary?)。
所以这里的第一件事:如果我不想使用指针,因为我在使用模板时对运行时分配不感兴趣,我想除了以上述方式复制临时创建的对象之外没有其他解决方案?
复制内容的实际问题现在来自 FileOutputter:当然不能复制一个 ofstream,那么如何复制包含流的 FileOutputter 对象?我想出了以下解决方案来克服这个问题:
struct FileOutputter {
// c_tor
FileOutputter() {}
// c_tor
explicit FileOutputter(const char* fname) {
mStream = std::make_shared<std::fstream>(fname, std::fstream::out);
}
// The copy c_tor will be invoked while creating any logger with FileOutputter
// FileLogger f(NoFilter(), SimpleFormatter(), FileOutputter("log.txt"));
// as all incoming paramters from the constructors stack frame are copied into the current instance of the logger
// as copying a file-stream is not permitted and not good under any means
// a shared pointer is used in the copy c_tor
// to keep the original stream until no reference is referring to it anymore
FileOutputter(const FileOutputter& other) {
mStream = other.mStream;
}
~FileOutputter() {
}
void out(const char* msg) const {
*mStream << msg;
}
std::shared_ptr<std::fstream> mStream;
};
不知何故,我不得不觉得这对于“简单的记录器类”来说似乎有点复杂,但是在这种情况下,这可能只是基于策略的设计方法的一个“问题”。
欢迎任何想法