IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage Java Discussion :

"Singleton" et factory


Sujet :

Langage Java

  1. #1
    Membre averti Avatar de BakaOnigiri
    Inscrit en
    Avril 2002
    Messages
    366
    Détails du profil
    Informations forums :
    Inscription : Avril 2002
    Messages : 366
    Points : 437
    Points
    437
    Par défaut "Singleton" et factory
    Bonjour,

    je pense que cette question doit être régulièrement posée, mais voilà, j'ai besoin d'avoir un singleton basée sur une classe abstraite, et donc j'ai plusieurs implémentations.


    Quel est le meilleur moyen, de faire une factory pour avoir un singleton ?

    Pour le moment j'ai codé çà comme çà : mais j'aime pas vraiment ce que j'ai fait

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    public abstract class CommHelper
    {
    	private static final Logger LOGGER = Logger.getLogger();
    	private static CommHelper INSTANCE = null;
     
    	public enum CommMode
    	{
    		SIMULATOR,
    		CORBA;
    	}
     
    	private String commHelperName;
     
    	protected CommHelper()
    	{
    	}
     
    	protected CommHelper(String name)
    	{
    		setCommHelperName(name);
     
    		LOGGER.info("CommHelper " + commHelperName + " initialized.");
    	}
     
    	private void setCommHelperName(String commHelperName)
    	{
    		this.commHelperName = commHelperName;
    	}
     
    	public static void initInstance(CommMode mode) throws CommInitException
    	{
    		switch(mode)
    		{
    			case SIMULATOR:
    				INSTANCE = new Simulator();
    				break;
     
    			case CORBA:
    				INSTANCE = new Corba();
    				break;
     
    			default:
    				throw(new CommInitException("Unknonw Comm Mode !"));
    		}
     
    		INSTANCE.init();
    	}
     
    	public static CommHelper getINSTANCE()
    	{
    		if(INSTANCE == null)
    		{
    			try
    			{
    				CommHelper.initInstance(CommMode.SIMULATOR);
    			}
    			catch(CommInitException e)
    			{
    				LOGGER.fatal("Erreur lors de l'initialisation : %s", e.getLocalizedMessage());
    			}
    		}
     
    		return INSTANCE;
    	}
     
    	public abstract void init() throws CommInitException;
     
    	public boolean shutdown()
    	{
    		LOGGER.info("Comm shutdown.");
    		return true;
    	}
    }
    J'ai 2 implémentations :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    public class Corba extends CommHelper
    {
    	private static final String NAME = "Corba";
     
    	public Corba()
    	{
    		super(NAME);
    	}
     
    	@Override
    	public void init() throws CommInitException
    	{
    		// TODO ::::
    	}
     
    	@Override
    	public boolean shutdown()
    	{
    		....
     
    		return super.shutdown();
    	}
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    public class Simulator extends CommHelper
    {
    	private static final String NAME = "Simulator";
     
    	public Simulator()
    	{
    		super(NAME);
    	}
     
    	@Override
    	public void init() throws CommInitException
    	{
    		// rien pour le simulateur
    	}
    }

    Donc çà me gène :

    1 - parceque c'est pas thread safe, et j'aime pas l'init pas défaut dans le getinstance
    2 - j'aimerais pouvoir initialiser le tout avec un truc du genre init("Corba") pour pouvoir ajouter des implémentations sans changer le code (donc un système de plugin, factory ?)


    Désolé pour cette question ultra récurrente, merci d'avance.

  2. #2
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    tu trouvera dans commons discovery, un classe utilitaire DiscoverSingleton qui satisfait à ton besoin, il me semble, elle s'utilise comme ça

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    public class MaFactory{
     public AbstractParent getInstance(){ 
       AbstractParent implementation = DiscoverSingleton.find(AbstractParent.class);
       return implementation;
     }
    Cette classe utilise le système des "Service" qui est apparu en java 1.4. On peux aussi passer des implémentation par défaut, etc, je te laisse décortiquer la doc

  3. #3
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Salut,


    Comment tu va déterminer le singleton à utiliser ?
    Pourquoi y-a-t-il une méthode shutdown dans ton singleton ?


    a++

  4. #4
    Membre averti Avatar de BakaOnigiri
    Inscrit en
    Avril 2002
    Messages
    366
    Détails du profil
    Informations forums :
    Inscription : Avril 2002
    Messages : 366
    Points : 437
    Points
    437
    Par défaut
    Pour déterminer quel implémentation je choisi, çà sera par un fichier de config de l'appli, voir un paramètre en ligne de commande.

    Il y a un shutdown, parce qu'il est prévus dans mon appli de pouvoir se déconnecter du serveur auquel je me connecte (en tout cas pour l'implémentation corba) avant de fermer complétement mon appli.

    Je vais étudier Discovery.

  5. #5
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Pour l'initialisation de chaque implémentation, il suffit de faire cela dans le constructeur. Surtout que c'est fait pour cela un constructeur...


    Sinon pour pas t'embêter avec le thread-safe, le mieux c'est de créer l'instance au chargement de la classe.

    Par exemple ici en utilisant les propriétés Java pour définir l'implémentation :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    abstract class CommHelper {
    	private static final Logger LOGGER = Logger.getLogger();
    	private static CommHelper INSTANCE = createInstance();
     
    	/**
             * La méthode est appellé par le ClassLoader au chargement
             * de la classe...
             */
    	private static CommHelper createInstance() {
    		String name = System.getProperty("comm-helper");
    		CommMode mode = CommMode.SIMULATOR; // par défaut
    		if (name!=null) {
    			mode = CommMode.valueOf(name);
    		}
    		switch (mode) {
    		case SIMULATOR:
    			return new Simulator();
    		case CORBA:
    			return new Corba();
    		}
    		throw new IllegalStateException("invalid comm-helper");
    	}
     
    	public static CommHelper getInstance() {
    		return INSTANCE;
    	}
     
    	public enum CommMode {
    		SIMULATOR,
    		CORBA;
    	}
     
    	private final String commHelperName;
     
    	protected CommHelper(String name) {
    		this.commHelperName = name;
    		// LOGGER.info("CommHelper " + commHelperName + " initialized.");
    	}
     
    	public boolean shutdown() {
    		LOGGER.info("Comm shutdown.");
    		return true;
    	}
    }

    a++

  6. #6
    Membre averti Avatar de BakaOnigiri
    Inscrit en
    Avril 2002
    Messages
    366
    Détails du profil
    Informations forums :
    Inscription : Avril 2002
    Messages : 366
    Points : 437
    Points
    437
    Par défaut
    Merci beaucoup adiGuba, mais j'ai choisis d'utiliser la classe apache commons DiscoverSingleton.

    En fait, principalement parce que comme çà je n'ai pas à modifier le code si je devais ajouter une nouvelle implémentation.

    Ma base avec les enum et les new en fonction d'un paramètre m'obligeais de lister de manière exhaustive toues les implémentations possible.

    Le DiscoverSingleton fait exactement ce que je veux, c'est génial.


    Merci à vous 2.

+ Répondre à la discussion
Cette discussion est résolue.

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo