there are folks in the comment section questioning if COR is the right pattern for logger or it can be done differently, here is my two cents on this, reason why chain of responsibility is the right pattern here: let's take example of log4j, we can enable certain log level in the system like ERROR or INFO etc, this is how the error levels are defined ALL < DEBUG < INFO < WARN < ERROR < FATAL < OFF e.g. if log level is set to warn, then only warn, error, fatal will be printed, rest all logs with other log levels will be disabled like debug, info etc will not be printed
Now you can see that chain of responsibility comes in handy here, lets say I have used warn as log level in log 4j and in code i have different logs like debug, info, error etc lets take error, it will go to all handlers and check what log level is enabled e.g. it will first go to debug handler, is it enabled, no, then go to next info and next warn, okay warn is enabled but the log level to be printed is error, then it will move to next handler i.e. error okay now it matches the log level to be printed and also at the system level warn is enabled and error handler is eligible for printing this log
There is a order of execution here where the request may or may not be fulfilled based on what log level is enabled and the order which the request should be served is defined by the chain of responsibility pattern i.e. ALL < DEBUG < INFO < WARN < ERROR < FATAL < OFF
How to decide when to use if-else / switch-case and when to use chain of responsibility pattern?
Like in case of logger since we already know about all the handlers and the chain order in advance why not use if-else statement for each log level
Spring Security Filter chain is the perfect example of this Design pattern in my opinion..where your authentication request goes through multiple Authentication Provider
Yeah, correct and not only Security Filter chain, it can be any Filters in Servlets or Interceptors in Struts2.
As a matter of fact, a set of middlewares that process a request in the request reply pattern happen to follow COR patter
Hey @shreyansh , can we also use factory pattern for logging as in the video itself the logging level can be determined using the type like info, debug or error and based on the type the implementing class can print the statement ? Just curious about the different approach in this logging specific problem. Although I understood the case where the rs 2000 were being fetched from ATM.
great example. Just one question, why can't we use switch case here to get exact match of that object type and call its method? if none is found, default case would return.
idk but does this design pattern really helps? The problem it is trying to solve can be easily solved by data structure or even by if else conditions if levels are not too many.
why i would want the flow to reach it to error via info or log when i can reach there directly?
or in vending machine if i want water why do i want the flow go via pepsi or coke??
Why do we use abstract class instead of normal class in Responsibility chain design pattern, when we don't have any abstract methods inside it?
how to decide whether to use factory or chain of responsbility principle in use cases like logger?
First of all great content. I love watching your playlist. 1 question, why not enums & static vars?
Man , you're the best person for this content❤❤❤ . Definitely recommending this channel to many.
can this can be used for employee detail check scenario,
say aadhar,pan,bank details checking one after one ??
Hi Shrayansh, can you give the insights about logging mechanism in distributed micro-services in HLD video?
Hey just a question, why can't we have three different objects and use something like a factory pattern to dynamically select the object on basis of some string(info, debug or error) and then invoke that object's logging function.
Why do we need to maintain a chain of responsibility
I was thinking this too.
This pattern might be more relevant for ATM where we want to dispatch the biggest note first and then the smaller ones....
for logger I think Factory should be fine?
@@dhvanilparikh6128 even in ATM, the simple coin DSA question would be able to solve it.
I feelfactory pattern should be a better candidate as well for a logger.
ATM is an excellent example where this pattern can be used. consider a user sends a request to withdraw 5000 with his card, the system can have different handler like Card Number checker, ATM card expiry checker, user's entered pinchecker and User's balance Checker. So all these checkers have a chain of responsibility. In case the user enters a card that is not even an ATM card then the request ends there, else the responsibility goes to next Card expiry and then pinchecker and then balance checker. In strategy or abstract factory,there is no chaining. We use one strategy or the other.
Forgive the bad formatting I'm typing this on my tablet using handwriting recognition
in the main class we have made an nested initialization to the Logger class.But in actual production code there is no such nested initialization in Log4j sdk
.How does that works internally then?
Most probably there is a wrapper class which returns the chained object
great video. one doubt is , cant we use simple factory pattern also to solve logger question ? based on log type in request, factory will return corresponding logger class and we will call log method in that class
Yeah mee too was thinking on the similar lines, that factory pattern would also be a great use-case for logger example.
I think shrayansh was more focused on explaining the chain of responsibility design pattern and therefore the example.
In one of my past companies a good use case of this pattern is in trading simulator setup (Obviously, Connecting the dots backwards :)
1. read_market_data -> 2. build_order_book -> 3. send_data_to_strategy....
Here the sequence of events form and share the chain of responsibility.
I was recently asked in an interview to design multi tier LRU cache where each layer will have increasing size and time of retrieval.
Can this be done using chain of responsibility considering if element is found, we need to populate it backwards in all previous layers for cache to be updated?
Yes, you can design a multi-tier LRU cache using the Chain of Responsibility pattern, ensuring that when an element is found in a higher tier, it gets populated backward in all previous layers for cache update.
can logger be implemented with observer pattern as well..? Where an error been written to multiple type of file or console..?
Awesome explanation.
can you help me understand why we prefer this design pattern over just simple if/else in the base class to create different logger object? to avoid unnecessary iteration over complete list
usage of design pattern is not mandatory at all, all your classes and relationships should fulfill SOLID principles,
So you can also do that with if-else till its not breaking solid principles.
. This logger can be implemented by strategy design pattern or abstract design pattern also ri8 since based on loglevel type we are implementing respective class.. whats is the use of chain of processing in classes as we know which log level type need to be used..
I also came up with that at first. It would be nice to see the arguments to use both. @ConceptandCoding
ATM is an excellent example where this pattern can be used. consider a user sends a request to withdraw 5000 with his card, the system can have different handler like Card Number checker, ATM card expiry checker, user's entered pinchecker and User's balance Checker. So all these checkers have a chain of responsibility. In case the user enters a card that is not even an ATM card then the request ends there, else the responsibility goes to next Card expiry and then pinchecker and then balance checker. In strategy or abstract factory,there is no chaining. We use one strategy or the other.
Forgive the bad formatting I'm typing this on my tablet using handwriting recognition
For the logger method, we could have simply used Factory design pattern to determine the correct logger as per the enum passed, why do we need a chain of responsibility pattern? In this scenario, why should an error message be even processed by InfoLogProcessor?
great explanation... thanks sir ji...
though the video length is 15min only.. one might need to spend more time understanding how this chain is transferring their responsibilities to next chained object.
Hey! for this logger implementation can we not use factory design pattern where it can provide me the instance of logger based on the requirement ?
Factory design pattern is creational design pattern, which mostly focus on creating of object.
So don't this we should use it here
@@ConceptandCoding Could you elaborate a bit on when we to use factory pattern and when to use chain of responsibility pattern? It seems like even in chain of responsibility pattern we are creating multiple objects ?
Hey . Like you said that vending machine can be designed by the state design pattern(in vending machine design video) and here you are saying that we can do this with chain of responsibility as well. I think ATM can also be designed by State design pattern . what do you think about it ?
Thank you Awesome explanation :)) waiting for next one!
Hi Avinash, pls find the git link gitlab.com/shrayansh8/interviewcodingpractise/-/tree/main/src
Also one gentle request, if you find video helpful pls do share it with your connections . thanks
@@ConceptandCoding Yep i have suggested your channel in my team they are finding to really helpful
Please keep posting in long run your efforts will pay off. You are making many early stage devs like me life easier
first of all, doing great work.
I have a suggestion that it should not be the responsibility of main method to invoke the info or debug logger rather the logProcessor should be responsible of creating the chain of log processors and main method just invoke the logger and then calls it for printing logs
Yes, that's a good suggestion buddy. The main method should simply invoke the logger, which then processes the logs through the chain. This keeps the main method clean and focused on its primary responsibilities.
Given the number of log levels are fixed. A EnumMap with Map would have been faster and maintainable compared to chain of responsibility design pattern.
Thanks for the video. One doubt why can't we use the factory pattern here?
Factory pattern is a creational type. It's job is to create objects.
But here we are not creating objects.
So the nature of work or you can say intention is different Gaurav
Can't we use a Factory pattern for logging? So, based on the LogLevel, we can return the corresponding object.
For a logger implementation, what is the actual difference between COR pattern and decorator pattern?
According to my understanding, in CoR every object has its own implementation and handling logic but in case of decorator pattern, we work on the same object and define different decorators to decorate the object. We can not break the flow in case of decorators as well.
[ Taken from refactoringguru ]
Chain of Responsibility and Decorator have very similar class structures. Both patterns rely on recursive composition to pass the execution through a series of objects. However, there are several crucial differences.
The CoR handlers can execute arbitrary operations independently of each other. They can also stop passing the request further at any point. On the other hand, various Decorators can extend the object’s behavior while keeping it consistent with the base interface. In addition, decorators aren’t allowed to break the flow of the request.
For this kind of design, why can't we use Factory pattern? Factory can return the required kind of class based on log level, and then use that to print the log in proper format.
This kind of design is used when you don't know which class can fulfill the request, so it goes in chain and which ever say yes i can fulfill, it will handle the request, in that case factory pattern will not fit
@@ConceptandCoding For ATM I agree that the COR pattern makes sense. For the logger use case we can only have a fixed number of levels that are there as an ENUM. So we can switch over the passed ENUM value to get the correct object. We can use a singleton factory to not generate new objects everytime
why can't we have different methods like logE, logI, logW?
Ideally one class should have only one responsibility as per SOLID principle.
Think of error reporting class, currently it is logging an error on console but in future we might wanna send some alarms to dev teams related to error count, we can build dashboard for service health.
If we have all logging method in one class then in future that class will be too cluttered
How to access car rental and car parking lot video ?
Those are accessed to members buddy. You will see join button at home page, there you can select "Unlock LLD" option.
binge watching to save myself from getting new membership next month . xD , but coding is taking time .
@@ConceptandCoding Thanks for keeping it at such low cost , means a lot for guys like me.
@@nitishprasadkushwaha :) even though it's low but it will make you think twice before you even think to purchase course for 5k or 10k rs.
Where is the repo link? Pz send me here.
gitlab.com/shrayansh8/interviewcodingpractise/-/tree/main/src/LowLevelDesign
iska gitlab link nhi hai kya?
Check here pls gitlab.com/shrayansh8/interviewcodingpractise/-/tree/main/src/LowLevelDesign
pls do english version
All latest videos are in English only, few were in hindi.
Will try to cover it in English, in Live LLD playlist (as I have covered few hindi topics in English in that playlist)
Isn't this design bad. Suppose in future we create a new handler and they fail to implement next logic properly then the whole system goes for a toss.
Sir code not working for me it is going in infinite loop😢
Debugged my issue sir, actually instead of if condition i was using while thats why it was going in infinite loop 😂😂😂
This could be simplified by using abstract method template with above implementation, so that you only care about how to log not when to log.
The code would look like
Your abstract Processor class would look like this:
constructor(nextLogger) { .... }
protected Logger nextLogger = null;
public final void log(int logLevel, String message){.
Kindly allow access to all videos @ConceptAndCoding
But ATM/Vending machine to State design ka use krte h na??
same question can be solved using different design patterns and different ways. So there is no 1 solution
May be more simple implementation
package LLDQuestions.Logger.LoggerBasic;
import java.io.IOException;
import java.io.PrintWriter;
enum LogLevel {
INFO, WARNING, ERROR
}
interface LogSink {
void log(String message);
}
class ConsoleSink implements LogSink {
@Override
public void log(String message) {
System.out.println(message);
}
}
class FileSink implements LogSink {
private String filename;
public FileSink(String filename) {
this.filename = filename;
}
@Override
public void log(String message) {
try (PrintWriter writer = new PrintWriter(filename)) {
writer.println(message);
} catch (IOException e) {
e.printStackTrace();
}
}
}
class Logger {
private LogLevel logLevel;
private LogSink logSink;
public Logger(LogLevel logLevel, LogSink logSink) {
this.logLevel = logLevel;
this.logSink = logSink;
}
public void log(LogLevel level, String message) {
if (level.ordinal() >= logLevel.ordinal()) {
String logMessage = "[" + level + "] " + message;
logSink.log(logMessage);
}
}
}
public class Solution {
public static void main(String[] args) {
LogSink consoleSink = new ConsoleSink();
LogSink fileSink = new FileSink("log.txt");
Logger consoleLogger = new Logger(LogLevel.INFO, consoleSink);
Logger fileLogger = new Logger(LogLevel.WARNING, fileSink);
consoleLogger.log(LogLevel.INFO, "This is an info message");
consoleLogger.log(LogLevel.WARNING, "This is a warning message");
fileLogger.log(LogLevel.ERROR, "This is an error message");
}
}
This is where we actually implement a Linked List from scratch to solve a real world problem!! And this proves why understanding datastructures from scratch is important and not simply use library classes. Great video!! 💯