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

Discussion :

design pattern Singleton

  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    47
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2008
    Messages : 47
    Par d�faut design pattern Singleton
    Hello'

    -> J'ai d�couvert les singleton, c'est ce qu'il me fallait.
    -> J'ai aucune connaissances sur le sujet, je fais que d�couvrir... j'aimerais savoir pourquoi ca ne marche pas
    -> piti� des mots simples dans vos reponses, je d�bute...

    -> mon but: rendre MainWindow singleton, et ensuite rendre SocketHandler singleton... Mais si j'y arrive une fois, je devrais pouvoir le faire deux fois.

    L'erreur qui s'affiche:
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    debug/main.o(.text+0x16a): In function `Z5qMainiPPc':
    C:/dev/HighStory/main.cpp:11: undefined reference to `Singleton<MainWindow>::Get()'
    debug/sockethandler.o(.text+0x4f5): In function `ZN13SocketHandler3lolEv':
    C:/dev/HighStory/sockethandler.cpp:16: undefined reference to `Singleton<MainWindow>::Get()'
    main.cpp
    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
    #include <QtGui/QApplication>
    #include "mainwindow.h"
    #include "sockethandler.h"
    #include "designpatterns.h"
     
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
     
     
    MainWindow* w=Singleton<MainWindow>::Get();
     
        w->show();
        w->showLogin();
     
     
        SocketHandler sh;
        sh.lol();
        return a.exec();
    }
    sockethandler.cpp
    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
    #include "sockethandler.h"
    #include "global_variables.h"
    #include "mainwindow.h"
    #include "designpatterns.h"
     
    SocketHandler::SocketHandler()
    {
        _qts = new QTcpSocket();
        _qts->connectToHost(QString(QTS_CONNECT_ADDRESS),QTS_CONNECT_PORT);
        qDebug("woot connected");
    }
     
     
    void SocketHandler::lol()
    {
        MainWindow* w=Singleton<MainWindow>::Get();
        w->errorAlert("LOOL");
    }
    mainwindow.cpp
    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
    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    #include "global_variables.h"
     
    MainWindow::MainWindow(QWidget *parent)
        : QMainWindow(parent), ui(new Ui::MainWindowClass)
    {
        ui->setupUi(this);
    }
     
    MainWindow::~MainWindow()
    {
        delete ui;
    }
    void MainWindow::showLogin()
    {
        // creating the login widget
        qmwLogin = new QWidget(this);
        qmwLogin->setObjectName(QString(QMW_LOGIN));
        qmwLogin->setGeometry(QRect(this->geometry().left(),this->geometry().top(),this->geometry().width(),this->geometry().height()));
        // now the controls
        leAccountID = new QLineEdit(qmwLogin);
        lePassword  = new QLineEdit(qmwLogin);
        pbLogin   = new QPushButton(qmwLogin);
        // names of em
        leAccountID->setObjectName(QString(QMW_LOGIN_ACCOUNTID));
        lePassword->setObjectName(QString(QMW_LOGIN_PASSWORD));
        pbLogin->setObjectName(QString(QMW_LOGIN_BTNLOGIN));
        // positioning
        leAccountID->setGeometry(QRect(qmwLogin->geometry().left()+100,qmwLogin->geometry().top()+100,60,20));
        lePassword->setGeometry(QRect(qmwLogin->geometry().left()+100,qmwLogin->geometry().top()+130,60,20));
        pbLogin->setGeometry(QRect(qmwLogin->geometry().left()+120,qmwLogin->geometry().top()+160,40,20));
        pbLogin->setText("Log in");
        // signals
        connect(pbLogin,SIGNAL(clicked()),this,SLOT(doLogin()));
        // show 'em
        leAccountID->show();
        lePassword->show();
        pbLogin->show();
     
        setCentralWidget(qmwLogin); // sets central widget
    }
    void MainWindow::hideLogin()
    {
        delete qmwLogin;
    }
    void MainWindow::doLogin()
    {
        QString *enteredAccountID = new QString(leAccountID->text());
        if(enteredAccountID->isEmpty() || enteredAccountID->isNull()) errorAlert(QString(ERROR_MISSING_ACCOUNTID));
        else {
            // preparating a packet to send.
            // sends it.
        }
     
    }
    void MainWindow::errorAlert(QString msg)
    {
        qmwErrorBox = new QWidget(this);
        qmwErrorBox->setGeometry(QRect(this->geometry().width()/2-150,this->geometry().height()/2-70,300,140));
        QLabel *ebMessage = new QLabel(qmwErrorBox);
        ebMessage->setGeometry(QRect(10,10,280,70));
        ebMessage->setText(msg);
        QPushButton *ebOk = new QPushButton(qmwErrorBox);
        ebOk->setGeometry(QRect(110,90,80,40));
        ebOk->setText("Ok");
        connect(ebOk,SIGNAL(clicked()),this,SLOT(errorOk()));
        qmwErrorBox->show();
    }
    void MainWindow::errorOk()
    {
        delete qmwErrorBox;
    }
    mainwindow.h
    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
    #include <QtGui/QMainWindow>
    #include <QChar>
    #include <QLineEdit>
    #include <QPushButton>
    #include <QFile>
    #include <QTextStream>
    #include <QLabel>
     
    #include "designpatterns.h"
     
    namespace Ui
    {
        class MainWindowClass;
    }
    class MainWindow : public QMainWindow, public Singleton<MainWindow>
    {
        Q_OBJECT
     
        friend MainWindow* Singleton<MainWindow>::Get();
        friend void Singleton<MainWindow>::Kill();
     
    public:
        void showLogin();
        void hideLogin();
        void errorAlert(QString msg);
    public slots:
        void doLogin();
        void errorOk();
     
    private:
        MainWindow (const MainWindow&){}
        MainWindow(QWidget *parent = 0);
        ~MainWindow();
        Ui::MainWindowClass *ui;
        QWidget *qmwLogin;
            QLineEdit *leAccountID;
            QLineEdit *lePassword;
            QPushButton *pbLogin;
        QWidget *qmwErrorBox;
    };
    designpatterns.cpp
    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
     
    #include "designpatterns.h"
    template <class T> T* Singleton<T>::m_i=0;
     
     
    template <class T>  T* Singleton<T>::Get()
    {
            if(m_i==0)
            {
                    m_i=new T();
            }
            return m_i;
    }
     
    template <class T> void Singleton<T>::Kill()
    {
            delete m_i;
            m_i=0;
    }
    designpatterns.h
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    template <class T> class Singleton
    {
    public:
            static T* Get();
            static void Kill();
    protected:
            static T* m_i;
            private:
            T& operator= (const T&){}
    };

  2. #2
    Mod�rateur
    Avatar de nouknouk
    Homme Profil pro
    Inscrit en
    D�cembre 2006
    Messages
    1 655
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 45
    Localisation : France

    Informations forums :
    Inscription : D�cembre 2006
    Messages : 1 655
    Par d�faut
    Salut,

    l'exception qui confirme la r�gle: le corps des fonctions (ie. le contenu de designpatterns.cpp) doit �tre inclus dans le m�me fichier que celui qui d�finit la classe elle-m�me (donc designpatterns.h).
    C'est le seul cas de figure (ie. dans les templates) o� c'est obligatoire.

    A noter que le singleton n'est pas le saint Graal des patterns et c'est normalement un pattern � �viter (on l'appelle parfois 'anti-pattern') car on en arrive vite � acc�der � l'objet singleton (ici la MainWindow) depuis n'importe o� � tort et � travers, au lieu de se poser la bonne question tout de suite : "n'y a-t-il pas un souci dans mon architecture ?".

    r�f�rences sur l'utilisation excessive de singletons :
    - en Anglais ici
    - traduction fran�ais ici

  3. #3
    Membre �m�rite

    Profil pro
    Inscrit en
    Mai 2007
    Messages
    774
    D�tails du profil
    Informations personnelles :
    �ge : 38
    Localisation : France, Finist�re (Bretagne)

    Informations forums :
    Inscription : Mai 2007
    Messages : 774
    Par d�faut
    l'exception qui confirme la r�gle: le corps des fonctions (ie. le contenu de designpatterns.cpp) doit �tre inclus dans le m�me fichier que celui qui d�finit la classe elle-m�me (donc designpatterns.h).
    C'est le seul cas de figure (ie. dans les templates) o� c'est obligatoire.
    Ce n'est pas tout � fait correct. C'est certes une solution, mais certains compilateur g�re mal l'inclusion de ce genre de "header", et ton .exe peut avoir une taille assez importante.

    Il existe une autre solution qui est, dans ton cas, d'ajouter cette ligne dans ton designpatterns.cpp
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    template class Singleton<MainWindow>;
    C'est pas forc�ment tr�s g�n�rique, mais c'est un autre moyen de faire, et aussi de limiter l'utilisation du pattern.

    G.

  4. #4
    Membre Expert

    Homme Profil pro
    D�veloppeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 49
    Localisation : France, Bouches du Rh�ne (Provence Alpes C�te d'Azur)

    Informations professionnelles :
    Activit� : D�veloppeur informatique
    Secteur : High Tech - Op�rateur de t�l�communications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Par d�faut
    Citation Envoy� par Gulish Voir le message
    Ce n'est pas tout � fait correct. C'est certes une solution, mais certains compilateur g�re mal l'inclusion de ce genre de "header", et ton .exe peut avoir une taille assez importante.

    Il existe une autre solution qui est, dans ton cas, d'ajouter cette ligne dans ton designpatterns.cpp
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    template class Singleton<MainWindow>;
    C'est pas forc�ment tr�s g�n�rique, mais c'est un autre moyen de faire, et aussi de limiter l'utilisation du pattern.

    G.
    Ca r�duit quand m�me fortement l'int�r�t d'un header contenant une d�finition template - ce n'est m�me plus histoire d'�tre g�n�rique, c'est une question de bon sens : pourquoi �crire du code template compliqu� si c'est pour ne pas l'utiliser autrement que dans un cas unique ?

    Pour ma part, et sans revenir sur mon appr�ciation singuli�re des singletons (dont, apr�s des ann�es de pratique, je ne vois toujours pas l'utilit�), je pr�conise de NE PAS �crire de singleton en se basant sur un template. Le code entourant un singleton est minuscule (en C++ : gu�re plus d'une petite dizaine de ligne). L'int�r�t de passer par une classe template est tr�s mod�r�, d'autant que l'�criture de celle-ci est complexe.

    Ensuite, on pourra discourir de l'utilit� d'une m�thode Kill(). Un singleton est cens� �tre valide pendant toute l'ex�cution du programme. Certes, cela signifie qu'il y aura, � la fin, quelques octets qui ne sont pas d�salou�s par l'application. Ne pas confondre �a avec une fuite de m�moire, puisque c'est sa raison d'�tre - et que l'OS va la r�cup�rer de toute fa�on. Kill() est au mieux une m�thode dangereuse - puisque le singleton peut tenir des ressources importantes qui peuvent �tre r�f�renc�es par d'autres objets.

    Bon, ensuite, sinc�rement, c'est quoi l'id�e d'une fen�tre principale qui devrait �tre accessible de partout ? Ca n'a pas vraiment de sens selon moi... Mais l�, on est plus cot� design que cot� code.
    [FAQ des forums][FAQ D�veloppement 2D, 3D et Jeux][Si vous ne savez pas ou vous en �tes...]
    Essayez d'�crire clairement (c'est � dire avec des mots fran�ais complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Caf�. C'est d�pass� tout �a.
    Et si vous �tes sages, vous aurez peut �tre vous aussi la chance de passer � la t�l�. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  5. #5
    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
    Par d�faut
    Citation Envoy� par secksy Voir le message
    L'erreur qui s'affiche:
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    debug/main.o(.text+0x16a): In function `Z5qMainiPPc':
    C:/dev/HighStory/main.cpp:11: undefined reference to `Singleton<MainWindow>::Get()'
    debug/sockethandler.o(.text+0x4f5): In function `ZN13SocketHandler3lolEv':
    C:/dev/HighStory/sockethandler.cpp:16: undefined reference to `Singleton<MainWindow>::Get()'
    La r�ponse est dans la F.A.Q. Pourquoi mes templates ne sont-ils pas reconnus � l'�dition des liens ?

    Citation Envoy� par Emmanuel Deloget Voir le message
    Pour ma part, et sans revenir sur mon appr�ciation singuli�re des singletons (dont, apr�s des ann�es de pratique, je ne vois toujours pas l'utilit�)
    J'ai le sentiment que souvent on utilise le singleton en se disant : je n'ai pas des variables globales car on m'a appris que c'est mal ... mais j'ai des singletons car c'est bien c'est un D.P. Alors qu'in fine, ce sont plus ou moins les m�mes probl�mes.
    Lorsque j'utilise le DP singleton, c'est plus souvent voisin d'un 'entrep�t' pour garantir l'acc�s � une instance d'une interface abstraite mont�e concr�tement par ailleurs plus que pour la n�cessit� d'avoir qu'une instance de la classe.

Discussions similaires

  1. D�serialisation et design pattern 'Singleton'
    Par tomnk dans le forum Persistance des donn�es
    R�ponses: 1
    Dernier message: 13/04/2009, 15h24
  2. scope application et design pattern singleton
    Par totoche dans le forum Servlets/JSP
    R�ponses: 1
    Dernier message: 01/10/2008, 15h56
  3. [Singleton] Classe static ou Design Pattern Singleton ?
    Par piloupy dans le forum Design Patterns
    R�ponses: 15
    Dernier message: 01/08/2008, 16h04
  4. R�ponses: 1
    Dernier message: 04/07/2008, 14h53
  5. Impl�mentation du design pattern singleton
    Par 0pierrot0 dans le forum C++
    R�ponses: 1
    Dernier message: 22/01/2008, 10h01

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