GoF design patterns are also hidden in the Java libraries that you use most often. It's easy to overlook the busy daily work, but once in a while, let's enjoy the beautiful design, which can be said to be a kind of art.
Common
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
...
Logger logger = LoggerFactory.getLogger(this.getClass());
...
Pattern 1-When using Logback
- slf4j-api-VERSION.jar
- logback-classic-VERSION.jar
- logback-core-VERSION.jar
Pattern 2-When using Log4j
- slf4j-api-VERSION.jar
- slf4j-log4j12-VERSION.jar
- log4j-VERSION.jar
Pattern 3-When using Java standard logger
- slf4j-api-VERSION.jar
- slf4j-jdk14-VERSION.jar
- rt.jar (Because it is a core Java library, it is from the beginning)
This is a scene to generate a Java logger (SLF4J). You can freely choose the logger implementation by simply replacing the jar file added to the classpath while keeping the source code. I feel the artistry that the interface and the implementation are separated very neatly.
Since there are various Java logging libraries [^ 2], I think that you often use different ones for each project. When trying to use the source of another project in my own project, if the logger used is different, I have to modify the source code or manage the logger's configuration file twice. It will not be beautiful.
The point of appreciation this time is that by preparing an adapter class, you can use it in the same way even if you replace the implementation class (logger). What's more, the implementation class replacement is the classic but simplest method of simply replacing the jar. We are in awe of the designer's chic design for us who use the library, as well as the beauty of the design. Let's watch it together below.
If you write the code at the beginning without using the Adapter pattern, it will be as follows.
Pattern 1-When using Logback
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.Logger;
...
LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
Logger log = lc.getLogger(this.getClass());
Pattern 2-When using Log4j
import org.apache.log4j.Logger;
...
Logger logger = Logger.getLogger(this.getClass());
Pattern 3-When using Java standard logger
import java.util.logging.Logger;
...
Logger logger = Logger.getLogger(this.getClass());
The description at the time of instance acquisition and the description of the import statement are different for each logger. Also, since the Logger
class to be instantiated is different, the methods that can be used for each are also different. If you change the logging library in this state, you will end up replacing a lot of source code. Moreover, if you were using a method that only exists in a particular logging library, you can't even replace it.
The code at the beginning uses the Adapter pattern. Let's look again.
First is the jar file to add to the classpath. Every logging library has three jar files, but they have the same role,
It has become.
The table below shows the types of logging libraries and the roles of jars.
Logback | Log4j | Java standard logger | |
---|---|---|---|
Common IF | slf4j-api-VERSION.jar | Same on the left | Same on the left |
IF implementation (adapter) | logback-classic-VERSION.jar | slf4j-log4j12-VERSION.jar | slf4j-jdk14-VERSION.jar |
Logging library implementation | logback-core-VERSION.jar | log4j-VERSION.jar | rt.jar |
Then, regardless of which logging library you are using, the logger instance will be uniformly generated as follows.
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
...
Logger logger = LoggerFactory.getLogger(this.getClass());
...
The contents of this getLogger
method are as follows.
java:org.slf4j.LoggerFactory.java
package org.slf4j;
...
//Classes in the common IF jar
public final class LoggerFactory {
...
public static Logger getLogger(String name) {
// org.slf4j.Create an instance of ILoggerFactory
//The implementation class is the class in the IF implementation (adapter) jar (see table below)
ILoggerFactory iLoggerFactory = getILoggerFactory();
// org.slf4j.Create an instance of Logger
//The implementation class is the class in the IF implementation (adapter) jar (see table below)
return iLoggerFactory.getLogger(name);
}
...
}
The implementation classes of ʻILoggerFactory and
Logger` are as follows. Both classes are included in the IF implementation (adapter) jar of their logging library.
Logback | Log4j | Java standard logger | |
---|---|---|---|
Implementation class of ILoggerFactory | ch.qos.logback.classic.LoggerContext | org.slf4j.impl.Log4jLoggerFactory | org.slf4j.jul.JDK14LoggerFactory |
org.slf4j.Logger implementation class | ch.qos.logback.classic.Logger | org.slf4j.impl.Log4jLoggerAdapter | org.slf4j.jul.JDK14LoggerAdapter |
If you follow this source code, you can see that the instances of LoggerFactory
and Logger
are created in the following flow. Which jar each class is included in is written in []. It is easy to understand if you are aware of it.
For Logback
org.slf4j.LoggerFactory [common IF jar]
↓
↓ org/slf4j/impl/StaticLoggerBinder.class file
↓ Find and instantiate
↓
org.slf4j.impl.StaticLoggerBinder [IF implementation (adapter) jar]
↓
↓ org.slf4j.ILoggerFactory interface
Instantiate LoggerContext that implements ↓
↓
ch.qos.logback.classic.LoggerContext [IF implementation (adapter) jar]
↓
↓ org.slf4j.Logger interface
Ch that implements ↓.qos.logback.classic.Instantiate Logger
↓
ch.qos.logback.classic.Logger [IF implementation (adapter) jar]
The point is that the finally generated Logger
is not a class included in the logging library implementation jar, but a class included in the IF implementation jar. This class holds a reference to the logging library in a member variable and calls it when logging.
By doing the above, the person who uses SLF4J will not refer directly to the instance of the logging library, but will refer to the IF implementation class corresponding to the adapter.
For Logback
People who use SLF4J
↓
↓ Use
↓
org.slf4j.Logger [common IF jar]
This entity is ch.qos.logback.classic.Logger [IF implementation (adapter) jar]
↓
↓ Used internally
↓
ch.qos.logback.core.XXXAppender [logging library implementation jar]
The Adapter pattern is sometimes referred to as the Wrapper pattern. ** Wrap in a new class to make it easier to use a class that is difficult to use as it is **. By the way, a class that is difficult to use as it is is a class in which the methods are not unified among similar classes or the source code is dirty.
No wonder the SLF4J interface should be clean. It's the result of being formatted with the Adapter pattern for the purpose of cleaning up.
For this example, I chose the one that maximizes the attractiveness of the Adapter pattern, but even if I do not do it thoroughly (IF, IF implementation, logging library implementation, I do not have to separate the jar files) ), ** Just create a wrapper class for a class that is difficult to use as it is, and you are using the Adapter pattern **.
Many experts have also commented on evaluating the Adapter pattern.
Hiroshi Yuki
Even in the world of programming, when what is already provided cannot be used as it is, it is often converted to the required form and then used. The Adapter pattern is a design pattern that bridges the "gap" between "what is already provided" and "what you need". ["Introduction to Design Patterns Learned in Java Language"](https://www.amazon.co.jp/ Introduction to Design Patterns Learned in Java Language-Yuki-Hiroshi / dp / 4797327030 /)
lang_and_engine
If you use the Adapter pattern well, it also has the effect of improving interpersonal relationships within the development team. When a low-skilled person wrote a mess of code, when another member tried to rewrite the source code of the class from the side, the programmer who coded it first said that it was "hurt". I feel it. In order to avoid this, the wrapper class is made one step higher, and the wrapper class side is enriched to improve the quality.
It's the real pleasure of programmers to be able to enjoy intellectual enjoyment just by looking at a single line of code without having to go to the museum.
If you are an engineer who sympathizes with the artistry of the Adapter pattern, please contact the hiring manager of our company (Qualysite Technologies Inc.). Contact Please!
-Design pattern to enjoy with Java library used frequently --Factory pattern -Design patterns to enjoy with frequently used Java libraries --Builder patterns -Design patterns to enjoy with frequently used Java libraries --Abstract Factory pattern
-Design patterns to enjoy with frequently used Java libraries --Facade pattern --Design patterns to enjoy with frequently used Java libraries --Adapter patterns
-Design patterns to enjoy with frequently used Java libraries --Template Method patterns -Design pattern to taste with Java library that is often used --Strategy pattern
[^ 1]: In the actual development scene, use a module management tool such as Maven to add the jar file. Please refer to Official reference of SLF4J here for the description method in the Maven configuration file (pom.xml).
[^ 2]: [Since there are too many java loggers to understand, I tried to organize them](http://www.bunkei-programmer.net/entry/2012/10/20/ java loggers I don't understand why there are too many, so organize them)
Recommended Posts