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

C++ Discussion :

Conception : Singleton et dérivation


Sujet :

C++

  1. #21
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 275
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 275
    Points : 10 985
    Points
    10 985
    Par défaut
    Un simple "g_" traduit tout aussi bien la nature unique de la bestiole.
    La principale chose reprochée aux variable globales, c'est le couplage invisible qu'elles introduisent. Et un singleton ne change rien à la donne.

    Je vois plus ça comme un jouet: "regardez je sais empêcher la création de plus d'une instance / je sais réaliser une construction paresseuse"
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  2. #22
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    J'y vois une différence : le pattern singleton me dit 'je ne dois pas créer un autre objet de la même classe' ce que la variable globale ne me dit pas. Il me le dit en relecture de code par un développeur bien sûr ; ce qui n'est pas toujours inutile vue les documents de conception qu'on est amené à lire...

  3. #23
    Membre actif
    Inscrit en
    Décembre 2003
    Messages
    272
    Détails du profil
    Informations forums :
    Inscription : Décembre 2003
    Messages : 272
    Points : 284
    Points
    284
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    [...](Curiously Recurring Template Pattern)[...]
    Par contre, je ne sais pas exactement pourquoi on dérive ainsi. Je suppose que ça aide à forcer l'instanciation du template...
    Le singleton doit connaître la classe (pour en stocker et renvoyer l'unique instance), il doit donc en dépendre (template).

    La classe ne doit pas pouvoir être instanciée autrement que par le singleton. On ne peut pas juste déclarer des Singleton<MaClasse>, il faut que la moindre référence à MaClasse fasse appel au mécanisme de singleton -> héritage.

    C'était bien ta question ?

  4. #24
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Oui.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  5. #25
    Membre actif
    Profil pro
    Inscrit en
    Juin 2002
    Messages
    577
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 577
    Points : 256
    Points
    256
    Par défaut
    @Luc
    Mais ... la dérivation est-elle vraiment pertinente? Ne s'agit-il pas plutôt d'un problème de réutilisation de service depuis un autre singleton ?
    Oui c'est exactement ça.
    Pour l'instant j'ai fait une classe abstraite CService et une CApp qui en dérive. Et CApp est mon singleton.
    Je ne vois pas vraiment d'autres moyens que la dérivation pour mon cas.
    Je vais prendre un peu + de temps ce soir pour analyser tes exemples de code.

    Déjà merci beaucoup pour vos réponses

  6. #26
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 275
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 275
    Points : 10 985
    Points
    10 985
    Par défaut
    Tu confonds alors spécialisation et utilisation.
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  7. #27
    Membre actif
    Profil pro
    Inscrit en
    Juin 2002
    Messages
    577
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 577
    Points : 256
    Points
    256
    Par défaut
    justement je me suis posé la question et je pense qu'il est plus logique d'effectuer une spécialisation de ma classe CService que de l'utiliser en l'instanciant dans ma classe CApp (métier).
    Car à mon sens le prog que je fais est un service, donc doit en dériver.

    @+

  8. #28
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 275
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 275
    Points : 10 985
    Points
    10 985
    Par défaut
    C'est substituable ?
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  9. #29
    Membre actif
    Profil pro
    Inscrit en
    Juin 2002
    Messages
    577
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 577
    Points : 256
    Points
    256
    Par défaut
    C'est substituable ?
    Que veux-tu dire ? Je ne vois pas ce que je peux ou non substituer ?

  10. #30
    Membre émérite
    Avatar de white_tentacle
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    1 505
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 1 505
    Points : 2 799
    Points
    2 799
    Par défaut
    Est-ce que partout où tu peux utiliser un CService, tu peux utiliser un CApp ?

    Si oui, l'héritage a un sens. Si non, l'héritage est une erreur de conception.

  11. #31
    Membre actif
    Profil pro
    Inscrit en
    Juin 2002
    Messages
    577
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 577
    Points : 256
    Points
    256
    Par défaut
    salut,
    et bien oui puisque de toute façon je n'utilise qu'un CApp partout dans mon code

    Ci dessous, mes 2 classes :

    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
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
     
     
    // Classe abstraite CService (destructeur virtuel pur)
    class CService
    {
    private :
    	LPCTSTR m_szSvcName;						//Nom du service
    	LPCTSTR m_szDisplayName;					//Libelle affiché du service
    	LPCTSTR m_szDescription;					//Description du service
    	LPTHREAD_START_ROUTINE m_pfnThread;			//Routine thread du service
    	LPVOID	m_pfnParam;							//param de la routine
     
    	HANDLE m_hTerminateEvent;
    	HANDLE m_hTerminateThread;
     
    	HANDLE m_hThread;						//Handle du thread crée pour le service
    	SERVICE_STATUS_HANDLE m_dwStatus;
    	BOOL m_bPause;
    	BOOL m_bRunning;
     
    	DWORD m_dwDesiredAccess;				//Flags de création du service
    	DWORD m_dwServiceType;
    	DWORD m_dwStartType;
    	DWORD m_dwErrorControl;
     
    	//Private copy constructor and operator= without defining them
    	CService( const CService& s );
    	CService& operator=( const CService& s );
     
    //Objet unique global (utile dans les fonctions statiques)
    	static CService* m_pObj;
     
    protected :
    	CService(	LPCTSTR name, LPCTSTR displayName, LPCTSTR desc,
    				LPTHREAD_START_ROUTINE routine,	LPVOID param,
    				DWORD dwDesiredAcces = SERVICE_ALL_ACCESS, DWORD dwServiceType = SERVICE_WIN32_OWN_PROCESS,
    				DWORD dwStartType = SERVICE_AUTO_START, DWORD dwErrorControl = SERVICE_ERROR_NORMAL) :
    		//Init list
    		m_hTerminateEvent(NULL), m_hTerminateThread(NULL),  m_hThread(NULL),  m_bPause(FALSE), m_bRunning(FALSE), m_dwStatus(0), 
    		m_szSvcName(name), m_szDisplayName(displayName),  m_szDescription(desc), 
    		m_pfnThread(routine), m_pfnParam(param),
    		m_dwDesiredAccess(dwDesiredAcces), m_dwServiceType(dwServiceType), m_dwStartType(dwStartType), m_dwErrorControl(dwErrorControl)
    	{
    		//We should ensure that only one call to this constructeur will be allowed
    		assert( !m_pObj );
    		m_pObj = this;
    	}
     
    	virtual ~CService() = 0
    	{
    		if(m_hThread)
    			CloseHandle(m_hThread);	
     
    		if(m_hTerminateEvent)
    			CloseHandle(m_hTerminateEvent);
     
    		if(m_hTerminateThread)
    			CloseHandle(m_hTerminateThread);
    	}
     
    public:
    	void ErrorHandler(const char *s, DWORD err);
     
    	BOOL SendStatusToSCM(DWORD dwCurrentState,
    					 DWORD dwWin32ExitCode,
    					 DWORD dwServiceSpecificExitCode,
    					 DWORD dwCheckPoint,
    					 DWORD dwWaitHint);
     
    	static void CtrlHandler(DWORD controlCode);
    	static void Main(DWORD argc, LPTSTR *argv);
     
     
    	virtual BOOL Management(LPTSTR arg);
     
    	BOOL Start();
    	void Resume();
    	void Pause();
    	void Stop();
     
    	void Terminate(DWORD error);
    	void RemoteTerminate();
    	bool IsTerminated();
     
    	void Add();
    	void Delete();
    };
     
    //Classe CApp
    class CApp : public CService
    {
    private:
     
    	//Request list
    	std::map<std::string, std::string> m_listReq;
    	CRITICAL_SECTION m_csListReq; 
     
    	//Event to terminate programm
    	HANDLE m_hEventTerminate;
     
    	CServer m_srv;
    	int m_num;
     
    	//App version
    	static const std::string m_version;
     
    	//unique static object
    	static CApp* m_pApp;
     
    	//@IP / Port de connexion
    	std::string m_ipOut;
    	unsigned short m_portOut;
     
    	//Private copy constructor and operator= without defining them
    	CApp( const CApp& s );
    	CApp& operator=( const CApp& s );
     
    	//Private constructor = DP Singleton.
    //Le compilo donne un warning car this dans la liste d'initialisation
    	CApp( unsigned short portIn, int nic, const std::string& ipOut, unsigned short portOut) :
    		CService( "SvcName", "SvcDisplayName", "SvcDescription", (LPTHREAD_START_ROUTINE) &CApp::_ServiceThread, this),
    		m_srv(portIn, nic, PROT_UDP, (PFN_CMD_MANAGER) &CApp::_CmdManager),		//Call the specific "CServer" constructor
    		m_ipOut( ipOut ), m_portOut( portOut ),
    	{			
    		//num machine
    		m_num = utils::GetTokenInt( utils::GetAddIp(nic), 4, '.' );
     
    		//Init critical sections
    		::InitializeCriticalSection( &m_csListReq );
     
    		//Create the TerminateEvent
    		m_hEventTerminate = ::CreateEvent(0, FALSE, FALSE, 0);
    	}	
     
    	//Private Destructor : Not virtual because CApp is not designed to be inherited
    	~CApp() {	
    		//Release any resources
    		::CloseHandle( m_hEventTerminate) ;
    		::DeleteCriticalSection( &m_csListReq );
    	}
     
    public:
     
    	//Get our unique CApp instance (Design Pattern Singleton)
    	//Returns a pointer to the unique instance
    	static CApp* CreateInstance( unsigned short portIn, int nic, const std::string& ipOut, unsigned short portOut)
    	{
    		return ( m_pApp ? m_pApp : m_pApp = new CApp(portIn, nic, ipOut, portOut) );
    	}
     
    	void DeleteInstance() {
    		delete m_pApp;	//ou delete this, ou sinon on aurait pu la faire static et donc appeler CApp::DeleteInstance
    	}
     
    	//Accesseurs
    	static CApp* GetInstance() {
    		return m_pApp;
    	}
     
    	int Init();
    	void Terminate();
    	bool IsTerminated();
     
    	//Each command message is managed by this static member function.
    	//Static because it is passed as a PFN_CMD_MANAGER parameter to our unique CServer object
    	static int _CmdManager(unsigned int id, const std::string& trame);
    	static DWORD _ServiceThread( LPDWORD param );	
    };
    et dans le main.cpp :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
     
    	//Create our unique global object
    	CApp* pApp = CApp::CreateInstance( 5000, 0, "192.168.0.1", 5001);
    	pApp->Management( argv[1] );		//--INSTALL / --DELETE	ou NULL ou autre ...

Discussions similaires

  1. [PHP 5.3] Conception problématique avec Singleton
    Par MegaBigBoss dans le forum Langage
    Réponses: 12
    Dernier message: 21/12/2011, 19h31
  2. [conception] soucis sur un singleton
    Par r0d dans le forum C++
    Réponses: 12
    Dernier message: 11/07/2007, 11h03
  3. [conception] Logger singleton global
    Par r0d dans le forum C++
    Réponses: 1
    Dernier message: 30/03/2007, 20h13
  4. [Conception] Classe abstraite ou singleton
    Par speedster dans le forum Langage
    Réponses: 6
    Dernier message: 24/03/2007, 10h39

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