Hello all general question is i like to build logger class that writes to single log file from different classes in my application what should the logger class be singletone or static class
views:
207answers:
6In C++ you'll want a singleton rather than a static. C++ does not allow you to control the order static objects are constructed and destructed, and if you tried to log before the static was constructed behaviour would possibly be undefined.
I'm not sure about Java.
The answer is of course "it depends."
First of all if I were you I would not reinvent the wheel and just use Log4j. If it does not serve your exact requirement, you are probably better off extending the one component of log4net that does not serve your needs (eg a custom loggin source) than startng from scratch. Secondly, a static class might be good enough for a simple logging class. For something more complex, a singleton class might be the way to go.
Don't use singleton or static, use Dependency Injection, i.e instantiate one instance in your main(), and pass a reference to that one instance to all dependent classes. Static and/or singleton is almost never necessary and quite often result in less elegant code.
What makes you think it should be either? What about a regular non-static class which can be instantiated on demand? And then make a single static instance of it available as the default logger. That way you get the best of both worlds: convenient global access to the logger and the ability to test it or temporarily use a different logger.
Another suggestion is to simply create a single instance and pass it as a parameter to every component of your class, as @disown suggests.
But if you make the class itself static or a singleton, you're just shooting yourself in the foot.
Edit
Example, in response to @Stephen's comment:
// define a logger class, a perfectly ordinary class, not a singleton, and without all static members
class Logger {
// ....
};
// create a single global *instance* of this class
Logger defaultLog;
void foo() {
// and now use the globally visible instance
defaultLog.Log("hello");
// or create a new one if that's what we need:
Logger newlog;
newlog.Log("hello");
}
There's no magic. This is exactly what the standard library does. std::cout
isn't a singleton. It is simply a global instance of class std::ostream
, a class which can also be instantiated normally if and when you need it.
In C++, you would use this idiom for lazy initialization:
Foo& getInstance()
{
static Foo instance;
return instance;
}
I would probably use a singleton, but either way, hide it behind a function or macro. Don't make people type
MySuperSpectacularLogger::GetInstance()->Log("adssdf");
Instead use:
void Log(cpnst string& msg) {
MySuperSpectacularLogger::GetInstance()->Log(msg);
}
or even better:
// Logs 'msg' with the filename and line number that generates it.
#define LOG(msg) \
MySuperSpectacularLogger::GetInstance()->Log(__FILE__, __LINE__, msg);