When I was defining the class with the singleton pattern myself, I suddenly wondered, so I looked it up. What is that question
Why implement with a singleton instead of a class method
about it. As I went deeper into this, I didn't understand why I was implementing the class using the singleton pattern in the first place.
In my private project, I wanted a class for managing properties, so I implemented the following:
PropertyService.java
import java.util.HashMap;
import java.util.Map;
public class PropertyService {
private static final PropertyService INSTANCE = new PropertyService();
private Map<String, String> props = new HashMap<String, String>();
private PropertyService(){
initializeProps();
}
public static PropertyService getInstance() {
return INSTANCE;
}
private void initializeProps() {
//Implement a method that initializes the property
//Insert the value manually for convenience.
props.put("a", "Tanaka");
props.put("b", "Suzuki");
props.put("c", "Sato");
}
public String getVal(String key) {
return this.props.get(key);
}
}
The above implementation has a singleton pattern. For me, I thought, "Because we need to be able to manage properties that are common to the project, we should use the" singleton pattern "that is implemented so that there is always one instance." However, it can also be implemented as follows using the above class and class method.
PropertyUtils.java
import java.util.HashMap;
public class PropertyUtils {
private static final HashMap<String, String> props = new HashMap<String, String>();
static {
//Property initialization process
props.put("a", "Tanaka");
props.put("b", "Suzuki");
props.put("c", "Sato");
}
public static String getVal(String key) {
return props.get(key);
}
}
It's a so-called utility class. This is easier to implement and seems to be able to centrally manage properties.
So why do we need to implement the singleton pattern? Why do we need "*** always only one instance ***" instead of implementing it in a class method?
For example, if you want to implement an interface, you cannot substitute it with a static method.
TestInterface.java
public interface TestInterface {
public void sayHello(String name);
}
TestImplements.java
public class TestImplements implements TestInterface {
private static final TestImplements INSTANCE = new TestImplements();
private TestImplements() {}
public static TestImplements getInstance() {
return INSTANCE;
}
@Override
public void sayHello(String name) {
System.out.println("Hello " + name + " !");
}
}
Of course, you can define a static method in the interface and define a static method with the same name in the implementation class, but it will be treated as a completely different method, not an override, so the advantage of implementing the interface Is gone. Rather, if you define a static method in the interface, you can use that method without creating an implementation class, so if you want to implement the interface as described above, you still have to use the singleton pattern.
When implementing static method in interface
public interface TestInterface {
public static void sayHello(String name) {
System.out.println("Hello " + name + " !");
}
}
You can use static methods without implementing them
public class TestImplements implements TestInterface {
...(Omission)...
public static void sayHello(String name) {
TestInterface.sayHello(name);
}
}
When overriding a method of an abstract class, the static modifier cannot be added, so it must be implemented as a singleton pattern.
TestAbstract.java
abstract public class TestAbstract {
abstract public void sayHello(String name);
}
TestExtends.java
public class TestExtends extends TestAbstract {
private static final TestExtends INSTANCE = new TestExtends();
private TestExtends() {}
public static TestExtends getInstance() {
return INSTANCE;
}
@Override
public void sayHello(String name) {
System.out.println("Hello" + name + " !");
}
}
For example, if you want to define a bean in spring, you must set an instance of the class as a bean. So if you want to make it a common class for your app and set that class as DI, you need to implement it in a singleton pattern.
If you want to set it to Spring Bean
@Configuration
public class BeanConfiguration {
@Bean
public TestInterface testInterface() {
return TestImplements.getInstance();
}
}
For example, if you want to inject a dependency with Autowired such as spring, the field to be injected cannot be static, so you need to implement it with a singleton pattern.
python
public class TestImplements implements TestInterface {
...(Omission)...
@Autowired
TestService testService;
...(Omission)...
}
However, although there is a way to inject dependencies into static fields, it seems to be a rather brute force implementation (see the site for reference).
You can inject dependencies into static fields
public class TestImplements implements TestInterface {
...(Omission)...
static TestService testService;
@Autowired
public void setTestService(TestService service) {
testService = service;
}
...(Omission)...
}
But after all, the setter needs to be non-static, so it must be implemented in a singleton pattern.
For example, in the case of "a class that implements only a method that always returns only a fixed value" like the following class, there is no reason to implement it in the singleton pattern.
TestSingleton.java
public class TestSingleton {
private static final TestSingleton INSTANCE = new TestSingleton();
private TestSingleton() {}
public static TestSingleton getInstance() {
return INSTANCE;
}
public void sayHello() {
System.out.println("HelloWorld");
}
}
In the case of the above class, you can implement it as a utility class as mentioned at the beginning.
This time, I was wondering why the singleton "only one instance can be created" design is advantageous for creating applications, so I studied it. The reason I thought about that is that, as mentioned above, *** some singletons can be replaced by static methods. *** *** When I wanted to use the singleton pattern in this study, I thought I had to find the advantage because it was the only "*** instance ***".
I have listed the cases where the singleton pattern should be implemented and the cases where it should not be implemented as far as I can think of, but I will add it as needed if I notice anything in the future.
reference: I tried to summarize the usage of the Singleton pattern Pros and Cons of Singleton. Carefully explain Java static methods! Let's learn usage examples and ideas together! I want to target static fields to @Autowired
Recommended Posts