[JAVA] Pourquoi implémenter avec singleton au lieu de la méthode statique

Question

Quand je définissais moi-même la classe avec le modèle singleton, je me suis soudainement demandé, alors j'ai cherché. C'est quoi cette question

Pourquoi implémenter en singleton au lieu de la méthode de classe

à propos de ça. En approfondissant cela, je n'ai pas compris pourquoi j'implémentais la classe en utilisant le modèle singleton en premier lieu.

Que voulez-vous dire

Dans mon projet privé, je voulais une classe pour gérer les propriétés, j'ai donc implémenté ce qui suit:

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() {
		//Implémenter une méthode pour initialiser les propriétés
		//Insérez la valeur manuellement pour plus de commodité.
		props.put("a", "Tanaka");
		props.put("b", "Suzuki");
		props.put("c", "Sato");
	}

	public String getVal(String key) {
		return this.props.get(key);
	}

}

L'implémentation ci-dessus a un modèle singleton. Pour moi, j'ai pensé: "Parce que nous devons être capables de gérer des propriétés communes à tous les projets, nous devrions utiliser un" modèle singleton "qui est implémenté de sorte qu'il y ait toujours une instance." Cependant, il peut également être implémenté comme suit en utilisant les classes et méthodes de classe ci-dessus.

PropertyUtils.java


import java.util.HashMap;

public class PropertyUtils {

	private static final HashMap<String, String> props = new HashMap<String, String>();

	static {
		//Processus d'initialisation de la propriété
		props.put("a", "Tanaka");
		props.put("b", "Suzuki");
		props.put("c", "Sato");
	}

	public static String getVal(String key) {
		return props.get(key);
	}

}

C'est une soi-disant classe d'utilité. Ceci est plus facile à mettre en œuvre et semble pouvoir gérer de manière centralisée les propriétés.

Alors, pourquoi avons-nous besoin de l'implémenter dans un modèle singleton? Pourquoi avons-nous besoin de "*** toujours une seule instance ***" au lieu de l'implémenter dans une méthode de classe?

Si vous devez utiliser un modèle singleton

Si vous souhaitez implémenter une interface

Par exemple, si vous souhaitez implémenter une interface, vous ne pouvez pas la remplacer par une méthode statique.

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 + " !");
    }

}

Bien sûr, vous pouvez définir une méthode statique dans l'interface et définir une méthode statique avec le même nom dans la classe d'implémentation, mais elle sera traitée comme une méthode complètement différente, pas une substitution, donc l'avantage d'implémenter l'interface Est parti. Au contraire, si vous définissez une méthode statique dans l'interface, vous pouvez utiliser cette méthode sans créer de classe d'implémentation, donc si vous souhaitez implémenter l'interface comme décrit ci-dessus, vous devez toujours utiliser le modèle singleton.

Lors de l'implémentation d'une méthode statique dans l'interface


public interface TestInterface {

	public static void sayHello(String name) { 
		System.out.println("Hello " + name + " !");
	}

}

Vous pouvez utiliser des méthodes statiques sans les implémenter


public class TestImplements implements TestInterface {

	...(Omission)...

	public static void sayHello(String name) {
		TestInterface.sayHello(name);
	}

}

Si vous souhaitez l'implémenter en tant que classe héritée d'une classe abstraite

Lors de la substitution d'une méthode d'une classe abstraite, le modificateur statique ne peut pas être ajouté, il doit donc être implémenté en tant que modèle singleton.

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 + " !");
	}

}

Si vous souhaitez régler sur DI

Par exemple, si vous souhaitez définir un bean au printemps, vous devez définir l'instance de classe en tant que bean. Donc, si vous voulez en faire une classe commune pour vos applications et que vous souhaitez définir cette classe comme DI, vous devez l'implémenter dans un modèle singleton.

Si vous souhaitez le définir sur Spring Bean


@Configuration
public class BeanConfiguration {

	@Bean
	public TestInterface testInterface() {
		return TestImplements.getInstance();
	}

}

Si vous souhaitez injecter des dépendances

Par exemple, si vous souhaitez injecter des dépendances avec Autowired telles que spring, vous ne pouvez pas rendre le champ injecté statique, vous devez donc l'implémenter dans un modèle singleton.

python


public class TestImplements implements TestInterface {
	
	...(Omission)...
	
	@Autowired
	TestService testService;

	...(Omission)...

}

Cependant, bien qu'il existe un moyen d'injecter des dépendances dans des champs statiques, cela semble être une implémentation plutôt agressive (voir le site pour référence).

Vous pouvez injecter des dépendances dans des champs statiques


public class TestImplements implements TestInterface {

	...(Omission)...
	
	static TestService testService;

	@Autowired
	public void setTestService(TestService service) {
		testService = service;
	}
	
	...(Omission)...

}

Mais après tout, le setter doit être non statique, il doit donc être implémenté dans un modèle singleton.

Quand tu n'as pas besoin d'utiliser une seule tonne

Lorsqu'il ne tient pas l'état

Par exemple, dans le cas d'une "classe qui implémente uniquement une méthode qui ne retourne toujours qu'une valeur fixe" comme la classe suivante, il n'y a aucune raison de se soucier de l'implémenter dans un modèle singleton.

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");
	}

}

Dans le cas d'une classe comme celle ci-dessus, vous pouvez l'implémenter en tant que classe utilitaire comme mentionné au début.

Résumé

Cette fois, je me demandais pourquoi le design d'une seule tonne "une seule instance peut être créée" serait un avantage pour créer une application, alors je l'ai étudié. La raison pour laquelle j'ai pensé à cela est que, comme mentionné ci-dessus, *** certains singletons peuvent être remplacés par des méthodes statiques. *** *** Quand j'ai voulu utiliser le modèle singleton dans cette étude, j'ai pensé que je devais trouver l'avantage car c'était la seule "*** instance ***".

J'ai énuméré les cas où il devrait être implémenté dans le modèle singleton et les cas où il ne devrait pas être implémenté dans la plage que je peux imaginer, mais je l'ajouterai si nécessaire si je remarque quelque chose dans le futur.

référence: J'ai essayé de résumer l'utilisation du modèle Singleton Pros and Cons of Singleton. Expliquez soigneusement la méthode statique de Java! Apprenons ensemble des exemples d'utilisation et des idées! Je souhaite cibler les champs statiques sur @Autowired

Recommended Posts

Pourquoi implémenter avec singleton au lieu de la méthode statique
Implémentez rapidement singleton avec enum en Java
Avantages de la méthode statique Java
Implémentez iOS14 UICollectionView avec CustomCell.
Utiliser le format nommé avec la méthode de format de Ruby
[Java] Pourquoi utiliser StringUtils.isEmpty () au lieu de String.isEmpty ()
J'ai essayé d'implémenter une fonction équivalente à Felica Lite avec HCE-F d'Android
Sortez avec un suffixe sur la méthode
Sortez avec un suffixe sur la méthode 2