Hériter d'un singleton

Hériter d'un singleton - Java - Programmation

Marsh Posté le 15-11-2002 à 14:29:23    

Toujours dans mes grands délires sur les singletons, je me demandais s'il était contre-indiqué d'hériter d'un singleton ? N'y a-t-il pas un risque "d'effet de bord incontrolable" (notamment, problème d'instanciation) ? La classe héritante est-elle aussi un singleton ? Si non, comment faire pour qu'elle en soit un aussi ?

Reply

Marsh Posté le 15-11-2002 à 14:29:23   

Reply

Marsh Posté le 15-11-2002 à 14:34:00    

qu'est ce que tu apelles singleton ?
 
montre la définition de cette classe ...

Reply

Marsh Posté le 15-11-2002 à 14:49:40    

Tout dépend de la façon dont est définie l'instance de ton singleton....Et la raison qui motive un héritage...Hériter d'un singleton, je vois pas l'intérêt., là comme ça....Tu as un exemple de cas d'utilisation, histoire qu'on se fasse une idée??

Reply

Marsh Posté le 15-11-2002 à 14:58:30    

Singleton de base :

Code :
  1. public class TestSingleton {
  2.     protected static TestSingleton ourInstance;
  3.     public synchronized static TestSingleton getInstance () {
  4.         if (ourInstance == null) {
  5.             ourInstance = new TestSingleton ();
  6.         }
  7.         return ourInstance;
  8.     }
  9.     private TestSingleton () {}
  10. }


 
Si tu hérites de ça, la méthode getInstance n'aura pas à être surchargée (la valeur de retour devra être du type de la nouvelle class, donc la signature sera différente).
Au mieux, tu peux peut être faire un truc du style, ms c plus tout à fait un vrai singleton :

Code :
  1. public class TestSingletonExtentded extends TestSingleton {
  2.     // Une ClassCastException sera lancée si TestSingleton.getInstance() à été appelé en premier (avant TestSingletonExtended.getInstance)
  3.     public static TestSingletonExtentded getInstance () throws ClassCastException {
  4.         if (ourInstance == null) {
  5.             ourInstance = new TestSingletonExtentded ();
  6.         }
  7.         return ((TestSingletonExtentded)ourInstance)
  8.     }
  9.     private TestSingletonExtentded () {}
  10. }


 
L'histoire du ClassCastException, c le seul pb que j'vois au premier abord...


Message édité par El_gringo le 15-11-2002 à 14:59:53
Reply

Marsh Posté le 15-11-2002 à 15:16:58    

ouais, ou alors dans l'optique de faire qqchose du genre :  
 
 

Code :
  1. public class SingletonExtended extends Singleton {
  2.    private static ExtendedSingleton;
  3.     private ExtendedSingleton(Singleton s) {
  4.         //blablabla
  5.     }
  6.  
  7.     private ExtendedSingleton() {
  8.          return this(super.getInstance());
  9.     }
  10.     public static ExtendedSingleton getInstance() {
  11.       ...
  12.      }

 
 
mais bon, pour faire un truc comme ça, jc'est pas dit que l'héritage soit indispensable..

Reply

Marsh Posté le 15-11-2002 à 15:24:20    

les singleton avec les méthodes static capudubec ! :o
 
Factory Rulez !!!
 

Code :
  1. public interface InterfaceDeTonObjet {
  2.     ...
  3. }


Code :
  1. public interface InterfaceDeObjetFactory {
  2.     public InterfaceDeTonObjet  getInterfaceDeTonObjet();
  3. }


Code :
  1. public class TonObjet implements InterfaceDeTonObjet {
  2.    private TonObjet() {};
  3.    public static class Factory implements InterfaceDeObjetFactory {
  4.       private final InterfaceDeTonObjet instance = new TonObjet();
  5.       public InterfaceDeTonObjet  getInterfaceDeTonObjet() {
  6.          return instance;
  7.       }
  8.    }
  9. }

Reply

Marsh Posté le 15-11-2002 à 15:25:28    

et avec ca, tu fais de l'héritage comme tu veux ! t'es plus emmerdé avec les statics !
 
de toute façon, j'ai arrêté les statics : ca devrait pas exister en java !

Reply

Marsh Posté le 15-11-2002 à 15:28:41    

public static void main(String[] arguments) {
    ...
}

Reply

Marsh Posté le 15-11-2002 à 15:30:43    

benou> Dès que tu maintiens des caches dont la durée de vie est susceptible d'être supérieure à la durée de vie usuelle d'un objet (exemple, sur un serveur), tu as besoin d'objets statiques.
 
Le pattern du singleton permet justement de faire ça à peu près proprement.

Reply

Marsh Posté le 15-11-2002 à 15:31:30    

ouais, bon, on peut faire avec des factory aussi, ça revient exactement, au même : tu aura de toutes façons un appel statique pour obtenir une instance, alors bon....
 
Ce que je fais habituellement, c'est que je fais une factory quand j'ai plusieurs Singletons qui travaillent sur le même bouzin....Genre :  
 
 

Code :
  1. public class User() {
  2.    //Methodes "comportementales"
  3. }
  4. public interface (ou abstract class, ca dépend) UserReader() {
  5.    //Pour obtenir des instances de User
  6. }
  7. public class UserReaderImpl implements (ou extends) UserReader() {
  8.     //Implémentation dépendant du modèle de données
  9. }
  10. public interface (ou abstract class, ca dépend) UserWriter() {
  11.    //Pour mettre à jour le modèle  de données à partir d'instances de User
  12. }
  13. public class UserWriterImpl implements (ou extends) UserWriter() {
  14.     //Implémentation dépendant du modèle de données
  15. }
  16. public class UserFactory() {
  17. private static UserReader;
  18. privet static UsertWriter;
  19. public static UserReader getReader() {
  20.    ....
  21. }
  22. public static UserReader getWriter() {
  23.    ....
  24. }
  25. }

 
 
Mais bon, si j'ai par exemple, un truc qui gère des properties système, et que je sais n'avoir aucun droit en écriture sur ces machins, ben je me passe de factory : ça fait une classe de moins....J'ai juste les classes PropertyReader et PropertyReaderImpl.....
 

Reply

Marsh Posté le 15-11-2002 à 15:31:30   

Reply

Marsh Posté le 15-11-2002 à 15:32:43    

El_Gringo a écrit a écrit :

public static TestSingletonExtentded getInstance () throws ClassCastException {
        if (ourInstance == null) {
            ourInstance = new TestSingletonExtentded ();
        }
        return ((TestSingletonExtentded)ourInstance)  
    }
 
    private TestSingletonExtentded () {}
}[/cpp]



 
J'ai peur qu'en utilisant ici le ourInstance défini dans la classe mère, "j'écrase" l'instance de cette classe mère par ma nouvelle instance de nouvelle classe, et que du coup, tout ceux qui utiliseront encore la classe mère utiliseront plutôt la nouvelle classe (je ne sais pas si c'est clair, mais c'est ça). Impression ?

Reply

Marsh Posté le 15-11-2002 à 15:36:14    

En fait, il vous manque une donnée : le singleton que je souhaite hérité, je ne peux pas le modifier, ce n'est pas moi qui l'ai développé, on me le donne compilé :(

Reply

Marsh Posté le 15-11-2002 à 15:40:35    

Pour ton message d'avant, là, "l'écrasement" de la valeur ourinstance, ouais, normalement, ça va tout te pourrir....
 
Mais tu dois modifier quoi, de ton singleton?? Son comportement?? Le retour de certaines méthodes???
 

Reply

Marsh Posté le 15-11-2002 à 15:42:16    

tu peux pas faire un deuxieme singleton qui va déleguer ce qu'il faut au premier ?

Reply

Marsh Posté le 15-11-2002 à 15:48:00    

_Mac_ a écrit a écrit :

 
 
J'ai peur qu'en utilisant ici le ourInstance défini dans la classe mère, "j'écrase" l'instance de cette classe mère par ma nouvelle instance de nouvelle classe, et que du coup, tout ceux qui utiliseront encore la classe mère utiliseront plutôt la nouvelle classe (je ne sais pas si c'est clair, mais c'est ça). Impression ?




 
Ha, bah oui, ça c sûr !
Ms ça dépend du comportement que tu veux.
Ce que j't'ai donné, ça fait que les 2 classes sont en fait un seul singleton...

Reply

Marsh Posté le 15-11-2002 à 15:56:23    

BifaceMcLeOD a écrit a écrit :

public static void main(String[] arguments) {
    ...
}




ce n'est qu'un point d'entré. C'est le seul truc static que j'ai dans mes programmes

Reply

Marsh Posté le 15-11-2002 à 15:57:07    

BifaceMcLeOD a écrit a écrit :

benou> Dès que tu maintiens des caches dont la durée de vie est susceptible d'être supérieure à la durée de vie usuelle d'un objet (exemple, sur un serveur), tu as besoin d'objets statiques.




pas du tout !
 
La durée de vie d'un objet n'a rien à voir avec les statics !

Reply

Marsh Posté le 15-11-2002 à 16:02:01    

gfive a écrit a écrit :

ouais, bon, on peut faire avec des factory aussi, ça revient exactement, au même : tu aura de toutes façons un appel statique pour obtenir une instance, alors bon....



 
ben non. Quand un objet à besoin d'accéder au singleton, soit tu lui file le singleton, soit tu lui passe l'instance de la factory. Cette Factory doit être construit une fois au début du programme et diffusée aux objet qui en ont besoin.
 
Le static c'est nul : imaginez le cas d'une appli serveur. Vous pourrez pas déployer votre appli 2 fois sur le même serveur si elle se sert de trucs static.
 
Et puis sur les projets un peu gros c'est arhituctéralement parlant très mauvaise : les méthodes static peuvent être appelées depuis n'importe quel objet de la JVM ! On a aucun contrôle là dessus.


Message édité par benou le 15-11-2002 à 16:02:41
Reply

Marsh Posté le 15-11-2002 à 16:34:52    

benou a écrit a écrit :

 
 
ben non. Quand un objet à besoin d'accéder au singleton, soit tu lui file le singleton, soit tu lui passe l'instance de la factory. Cette Factory doit être construit une fois au début du programme et diffusée aux objet qui en ont besoin.
 
Le static c'est nul : imaginez le cas d'une appli serveur. Vous pourrez pas déployer votre appli 2 fois sur le même serveur si elle se sert de trucs static.
 
Et puis sur les projets un peu gros c'est arhituctéralement parlant très mauvaise : les méthodes static peuvent être appelées depuis n'importe quel objet de la JVM ! On a aucun contrôle là dessus.




 
Mais... on peut pas faire un singleton dans utiliser les statics. Pourtant les singleton, c qd même difficile de s'en passer.
Et puis tes classes utilitaires que t'as passé quelques fois, elles ont que des méthodes statiques....

Reply

Marsh Posté le 15-11-2002 à 16:45:42    

gfive a écrit a écrit :

Pour ton message d'avant, là, "l'écrasement" de la valeur ourinstance, ouais, normalement, ça va tout te pourrir....
 
Mais tu dois modifier quoi, de ton singleton?? Son comportement?? Le retour de certaines méthodes???
 
 




 
En gros, oui : l'idée était de pouvoir faire un super.maMethode dans les surcharges quand ça m'arrange, et conserver certaines autres méthodes. Le truc classique, quoi !

Reply

Marsh Posté le 15-11-2002 à 16:51:48    

El_Gringo a écrit a écrit :

 
 
Mais... on peut pas faire un singleton dans utiliser les statics. Pourtant les singleton, c qd même difficile de s'en passer.
Et puis tes classes utilitaires que t'as passé quelques fois, elles ont que des méthodes statiques....




ouais mais c'est de la fainéantise ... c'est plus pratique pour tester.
 
et puis bon, c'est vrai que j'y susi allé un peu fort : il peut être util d'utiliser des statics, mais que dans des cas très limités.
Par exemple, pour des méthodes utilitaires c'est complétement normal d'utiliser des statics.  
Pour des trucs qui seront toujours générale à la JVM aussi genre des méthodes permettant de copier des fichier ou des trucs dans le genre. Mais il faut vraiment que le choix soit raisonné !!
 
souvent les gens mettent un static à la vavite parce que c'est plus pratique à utiliser.
 
Et pusi quand on parle de singleton, n'oublie pas que si tu utilise le static ce sera un singletno pour toute la JVM ! pas seulement pour ton appli !

Reply

Marsh Posté le 15-11-2002 à 17:23:04    

Benou : beuh....pour un serveur, tu va pas le lancer 2 fois dans le même process, quand même....Et 2 instances de JVM qui tournent sur une même machine ne partagent pas leurs static, hein!!
Et bon, un serveur qui écoute sur un port donné, amuse toi à en lancer 2 instances sur une même machine, qu'on rigole! :D:D Et si c'est 2 instances avec un port différent, ben ça peut pas être statique, CQFD, et toc! :D:D
 
Enfin bon, c'est vrai, le static, on dit souvent que c'est mal, et tout, mais bon, par expérience, ça sert, quand même....
 
Regarde, bêtement, un système de logger, ou de gestion de connection DB....Ben il vaut mieux que ce soit statique, ce genre de bouzin, que tes streams se marchent pas dessus, non??

Reply

Marsh Posté le 15-11-2002 à 17:48:23    

qu'est ce que tu racontes ??? pfioulala !!
 
prend le cas d'un conteneur de servlet. Si tu as écris une API avec des statics partout, tu ne pourra pas utiliser cette API dans 2 web-app (2 sites) sur le même serveur ! ou bien bravo les effets de bord ! :/
 
les exemples que tu sites sont typiquement ceux que j'aurais utilisé comme contre exemple :D
Si ton logger est static, 2 sites Web sur le même serveur vont mélanger leurs logs dns le même fichier. Pareil pour la gestion de connection à la base de donnée !
 
En gros faut voir ce que tu veux faire :  
 - si ce que tu veux c'est faire un petit traitement indépendants à ton appli (genre des petites méthodes utilitaires, etc ...), des méthodes statiques sont parfaitement adaptés
 - si ce que tu veux faire c'est rendre un service (de logging, de management de connexion DB, etc) pour une application, C'est des objets qu'ils faut utiliser et les passer à tes classes qui en ont besoin.

Reply

Marsh Posté le 15-11-2002 à 17:52:15    

benou a écrit a écrit :

 
pas du tout !
 
La durée de vie d'un objet n'a rien à voir avec les statics !




Dès lors que l'on vit dans un monde (Java) où la durée de vie est liée à l'attachement (en anglais, reachability), si. Parce qu'il faut, pour que l'objet continue à vivre, qu'une référence sur lui existe. Et le plus simple pour obtenir cela, c'est qu'un symbole le référençant existe depuis la naissance de l'objet jusqu'à sa mort.
 
Donc si l'on veut disposer d'un objet dont la durée de vie soit celle du programme, je ne vois pas beaucoup de moyens autre que l'objet statique (à part bien sûr la persistance...  :sarcastic: ), i.e. un objet qui existe tant que sa classe existe.

Reply

Marsh Posté le 15-11-2002 à 17:53:45    

 :o houlala ...
dis moi que t'es pas sérieux s'il te plait ...  :sarcastic:

Reply

Marsh Posté le 15-11-2002 à 17:56:28    

benou a écrit a écrit :

 
 
ben non. Quand un objet à besoin d'accéder au singleton, soit tu lui file le singleton, soit tu lui passe l'instance de la factory. Cette Factory doit être construit une fois au début du programme et diffusée aux objet qui en ont besoin.
 
Le static c'est nul : imaginez le cas d'une appli serveur. Vous pourrez pas déployer votre appli 2 fois sur le même serveur si elle se sert de trucs static.




Ben non, gros malin : quand on lance 2 fois l'appli, elle tourne dans 2 JVM différentes (c'est d'ailleurs un gros b... pour les faire communiquer derrière...)
 

Citation :


Et puis sur les projets un peu gros c'est arhituctéralement parlant très mauvaise : les méthodes static peuvent être appelées depuis n'importe quel objet de la JVM ! On a aucun contrôle là dessus.


Encore une erreur. D'abord, les méthodes statiques sont sujettes à la protection habituelle (public/privé/protégé), et précisément sur un gros serveur, tu as souvent besoin d'un contexte global, dont l'accès sera évidemment synchronisé si tu as plusieurs threads.
 
L'avantage du singleton est précisément de plaquer la notion de boite noire et d'encapsulation sur la notion de variable globale, et permet de retrouver du contrôle, puisque l'accès aux différents "champs"/"éléments"/ce-que-tu-veux de la ou les variables globales se fait/font uniquement par des accesseurs, comme pour tout objet qui se respecte.

Reply

Marsh Posté le 15-11-2002 à 17:56:49    

Ben....je suis pas forcément d'accord, hein..nottament pour le gestionnaire de connections : si tu as un pool de connections, il est indispensable que ce soit le même pour tout le monde....Et pour un logger tu peux vouloir du mélange, justement, si tu fais, par exemple, un système où tu dois logger en "temps réel", je veux dire par là, si l'ordre des actions est important (typiquement, outil de stat pour des jeux de rapidité, ou comme ça) ben...t'as besoin que ça se mélange..

Reply

Marsh Posté le 15-11-2002 à 18:00:51    

Désolé, je viens juste de lire les derniers posts... :o Je vois que j'avais du retard...
 
benou> Tu cites le cas des logs ou des connexions à la BD. Mais justement dans ces cas-là, on va utiliser un gestionnaire centralisé, parce qu'il s'agit d'une ressource critique. Et ce gestionnaire centralisé, que va-t-il contenir ? Un table de hachage basé sur le thread courant. Effectivement, on aurau autant de loggeurs et de connexions BD que de clients connectés dans notre serveur, mais on y accédera quand même par un singleton, donc in fine un attribut statique.
 
edit> Encore trop tard  :p


Message édité par BifaceMcLeOD le 15-11-2002 à 18:01:25
Reply

Marsh Posté le 15-11-2002 à 18:01:03    

gfive a écrit a écrit :

Ben....je suis pas forcément d'accord, hein..nottament pour le gestionnaire de connections : si tu as un pool de connections, il est indispensable que ce soit le même pour tout le monde....Et pour un logger tu peux vouloir du mélange, justement, si tu fais, par exemple, un système où tu dois logger en "temps réel", je veux dire par là, si l'ordre des actions est important (typiquement, outil de stat pour des jeux de rapidité, ou comme ça) ben...t'as besoin que ça se mélange..




tu peux le vouloir, mais c'est pas forcément ce que tu veux faire. C'est tout à fait naturel de vouloir que 2 sites webs différents aient des logs différents ...

Reply

Marsh Posté le 15-11-2002 à 18:02:12    

Ca "marche" comment un objet qui contient une méthode statique ? Que fait la JVM quand elle voit une telle classe ?

Reply

Marsh Posté le 15-11-2002 à 18:03:03    

Mais j'ai pas dit que c'était la panacée non plus, hein!! C'est pas adapté à toutes les utilisations! Mais il y a des cas où tu en as absoluement besoin!
 


Message édité par gfive le 15-11-2002 à 18:04:53
Reply

Marsh Posté le 15-11-2002 à 18:07:22    

BifaceMcLeOD a écrit a écrit :

 
Ben non, gros malin : quand on lance 2 fois l'appli, elle tourne dans 2 JVM différentes (c'est d'ailleurs un gros b... pour les faire communiquer derrière...)




... t'as du comprendre dans mon autre post ce que je voulais dire. Un autre exemple : les serveurs d'applications (EJB, etc ...) 1 serveur = plusieurs applications
donc si ces différentes applications utilisent la même API qui a des trucs statics où il ne faut pas, ca va pas bien marcher !
 

BifaceMcLeOD a écrit a écrit :

 
Encore une erreur. D'abord, les méthodes statiques sont sujettes à la protection habituelle (public/privé/protégé), et précisément sur un gros serveur, tu as souvent besoin d'un contexte global, dont l'accès sera évidemment synchronisé si tu as plusieurs threads.




J'ai jamais parlé des problèmes d'accès concurent ... ca n'a rien à voir
 

BifaceMcLeOD a écrit a écrit :

L'avantage du singleton est précisément de plaquer la notion de boite noire et d'encapsulation sur la notion de variable globale, et permet de retrouver du contrôle, puisque l'accès aux différents "champs"/"éléments"/ce-que-tu-veux de la ou les variables globales se fait/font uniquement par des accesseurs, comme pour tout objet qui se respecte.




Je ne remet pas en cause la notion de singleton. C'est juste que rendre un singleton static c'est faire un singlton pour toute la JVM ! pas seulement pour une application ...
 
regarde dans toutes les API connues, il n'y quasiment aucun static ou bien seulement pour des petites fonctions utilitaires.

Reply

Marsh Posté le 15-11-2002 à 18:07:42    

Ben, j'imagine (mais je sais pas) que c'est le ClassLoader qui fait ça : quand il charge la classe, il réserve la mémoire et les pointeurs pour les attributs statiques, et il exécute tout ce qui est dans un champ static { }
 
A ce propos, Benou, après réflexion, pour les Web-apps, Tomcat utilise un ClassLoader par zone....donc, si tu te démerdes bien avec tes fichiers .class, tu dois pas être emmerdé..

Reply

Marsh Posté le 15-11-2002 à 18:10:38    

gfive a écrit a écrit :

Mais j'ai pas dit que c'était la panacée non plus, hein!! C'est pas adapté à toutes les utilisations! Mais il y a des cas où tu en as absoluement besoin!



Ben y en a pas des masses : y a le cas de la méthode main et le cas d'un Singlton pour la JVM (genre le system.out, un générateur d'identifiant uniques etc ...).  
 
Les autres utlisations c'est plutot pour une raison de facilité : les méthodes utilitaires , etc ...


Message édité par benou le 15-11-2002 à 18:14:05
Reply

Marsh Posté le 15-11-2002 à 18:13:07    

gfive a écrit a écrit :

Ben, j'imagine (mais je sais pas) que c'est le ClassLoader qui fait ça : quand il charge la classe, il réserve la mémoire et les pointeurs pour les attributs statiques, et il exécute tout ce qui est dans un champ static { }
A ce propos, Benou, après réflexion, pour les Web-apps, Tomcat utilise un ClassLoader par zone....donc, si tu te démerdes bien avec tes fichiers .class, tu dois pas être emmerdé..




 
C'est pas le ClassLoader qui fait ca : c'est un méchanisme interne à la JVM.
 
Ta remarque es pas conne : est ce que 2 classes chargées par 2 ClassLoader sépareés ont leurs attributs statiques communs ?
Je voterai pour oui, mais ca demande un petit test. (je reviens tout à l'heure ;))

Reply

Marsh Posté le 15-11-2002 à 18:16:29    

remarque : dans le cas où tu fosu le jar dans la partie common pour que toutes les webapp puissent se servir de l'API, le ClassLoader sera le même. Donc y a au moins un problème pour ce cas là !

Reply

Marsh Posté le 15-11-2002 à 18:24:25    

ouais, effectivement, ça demande un bidouillage savant pour pas se planter, mais bon...On a eu des cas à la con, comme ça, au boulot, pour adapter une appli pensée en single client vers du multi-client....Ben c'est une galère! :D
Enfin bon, on peut en débattre 107 ans sans jamais arriver à tomber d'accord :D
Mais t'es quand même un furieux d'aller tester ça u vendredi à 18h27! :D

Reply

Marsh Posté le 15-11-2002 à 18:33:23    

c'est clair  :pt1cable:  
mais bon, je suis super curieux ... on me changera pas ! ;)
 
j'ai testé, et effectivement, 2 classes identiques chargés par des ClassLoader différents n'ont pas leurs attributs statics communs.  [:wam]  
J'aurais vraiment pas cru ! j'ai appris un truc aujourd'hui  [:z-bob]

Reply

Marsh Posté le 15-11-2002 à 18:35:11    

bah heureusement!........ou pas!! :D:D
 
Bon, bière/fléchettes time, sur ce! :)

Reply

Marsh Posté le 15-11-2002 à 20:51:46    

bah dans le cas des web-app, le mieux c'est encore d'instancier les singletons dans un listener et de les ratacher au contexte applicatif, non ?

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed