This question is asked in so many low level design rounds but I couldn't find any implementation that I could fully understand. So I decided to implement a very basic design from scratch and expand upon it. Here I've just used Singleton pattern and Observer pattern.
The Logger class is a singleton class and a subject (in observer context) which is having a list of panels/consoles that display different kind of logs. I know I am supposed to have an addObserver method here, but I've just added them in constructor for now.
public class Logger {
private static final Logger instance = new Logger();
private final List<IPanel> panelList;
private Logger() {
this.panelList = new ArrayList<>();
panelList.add(new InfoPanel());
panelList.add(new CriticalPanel());
}
public static Logger getInstance() {
return instance;
}
public void log(Level level, String message) {
for (IPanel panel : panelList) {
if (panel.canPrint(level)) {
panel.print(message);
}
}
}
}Different levels of type of logs, ERROR - most severe criticality.
public enum Level {
INFO, DEBUG, ERROR
}IPanel is the observer interface, which different type of consoles / panels can implement. The canPrint(Level level) method checks whether the respective panel should print a log or not based on the severity level.
public interface IPanel {
void print(String message);
boolean canPrint(Level level);
}Two concrete panels implement the above.
CriticalPanel : only for error logs.
public class CriticalPanel implements IPanel {
public void print(String message) {
System.out.println("CRITICAL_PANEL " + System.currentTimeMillis() + " : " + message);
}
public boolean canPrint(Level level) {
return level.ordinal() >= Level.ERROR.ordinal();
}
}InfoPanel : for all kind of logs.
public class InfoPanel implements IPanel{
public void print(String message) {
System.out.println("INFO_PANEL " + System.currentTimeMillis() + " : " + message);
}
public boolean canPrint(Level level) {
return level.ordinal() >= Level.INFO.ordinal();
}
}Client that can use the above logger:
public class Main {
private static final Logger logger = Logger.getInstance();
public static void main(String[] args) {
logger.log(Level.ERROR, "This is an error message");
logger.log(Level.INFO, "This is an info message");
}
}I know it's not much but it's honest work. Can you please suggest how to exapnd on it and/or make it better? What areas to improve, like concurrency etc.?