Patron singleton (avec protection contre les multi thread), tutorial patron 1

Soyez le premier à donner votre avis sur cette source.

Vue 16 125 fois - Téléchargée 644 fois

Description

Définition: Patron
Un patron est une atructure de programmation en orienté objet pour faire un option spécifique dans n'importe quel programme. C'est comme un algorithme de trie. Les algo sont déjà créé et ils sont fonctionnel dans n'importe quel programme. La différence, c'est qu'un patron de conception, c'est une option spécifique a un problème récurent. Il faut avoir un très bonne connaissance en orienté objet et le UML est tr`se vite nécessaire dasn les patron d'un certain niveau. C,est pour ça que les tutoriaux sont classé d'intermédiaire a avancer, sauf le Singleton qui est le plus facile a utiliser.

Définition: Singleton
Un singleton est la création d'une seule instance d'un objet. En théorie, un singleton sert a permettre d'avoir une seule class, masi on peut aussi le programmer pour permettre d'afficher une seule form ou conservé le résultat d'une requête SQL (comme la liste des employés qui change très peu en une journée). Donc un Singleton est une façon de programmer sa class pour qu'elle se charge en mémoire une fois et qu'après ont puisse l'utiliser de n'importe où sans devoir la recharger en mémoire.

Définition: Instance
Une instance est un objet en mémoire. Si on ouvre 2 msgbox, on a 2 instances en mémoire. Un singleton empêche d'avoir 2 instances en mémoire et permet d'en avoir une seule.

Important a regarder dans un Singleton

Shared instance As tb_users
Cette variable est la base du Singleton. Elle s'appel en tout temps Instance (par convention) elle est du même type que la class

Private Sub New()
Doit-être toujours private pour raison de sécurité

Shared Function getInstance() As tb_users
Par convention elle s'appel toujours getInstance. C'est ici le tour de passe passe qui permet de charger une seule fois en mémoire la class

SyncLock GetType(tb_users)
Ici la protection contre les multi thread trop rapide

Source / Exemple :


Public Class tb_users
    Private listeID As Hashtable
    'Déclaration de l'instance Singleton
    Shared instance As tb_users

    'Pas oublier de mettre Private pour la sécurité
    Private Sub New()
        MyBase.New()
        listeID = New Hashtable
        Dim connexion As Type.ConnexionVar = BaseDonnee.ouvertureRSTThread("select id,Prénom,Nom, utilisateur, admin from tb_users where " & EnableDate(Now))

        For i As Integer = 0 To UBound(connexion.drd)
            BaseDonnee.readThread(connexion)
            Dim usager As Type.users
            usager.prenom = BaseDonnee.itemThread(1, connexion)
            usager.nom = BaseDonnee.itemThread(2, connexion)
            listeID.Add(BaseDonnee.itemThread(0, connexion), usager)
        Next i
    End Sub

    'Voici le patron Singleton
    Shared Function getInstance() As tb_users
        'Si le singleton est pas créé, alors faut le créé
        If IsNothing(instance) Then
            'Protection contre les thread trop rapide
            'Il est mis ici après le IsNothing pour permettre d'être rapide une fois créé
            SyncLock GetType(tb_users)
                '2e valiation de l'instance, au cas que 2 thread soit entré ici
                'le 2e thread sera bloquer et le premier va créé l'instance
                'mais après, on veut que le 2e thread en crée pas une autre
                If IsNothing(instance) Then
                    'Création de l'instance
                    instance = New tb_users
                end if
            End SyncLock
        End If
        Return instance
    End Function

    Public Function getUsers(ByVal id As Integer) As Type.users
        getUsers = listeID.Item(id)
    End Function
End Class

Conclusion :


J'ai mis un 2e exemple dans le zip, mais ce coup-ci avec des forms à la place

Si vous avez moindrement des questions, écrivez ici, ça va surement en aider d'autre
S'il y a un bout du tutorial qui est pas clair, n'hésiter pas non plus

Codes Sources

A voir également

Ajouter un commentaire

Commentaires

Messages postés
2336
Date d'inscription
samedi 14 juillet 2001
Statut
Membre
Dernière intervention
5 mai 2009
4
oui, il doit y avoir un problème dans ton singleton.
en passant, mieux vaut toujours mettre tes composant private et faire un getTexte à la place

ceci serait suffusant
console.writeline(form2.getInstance().getTexte())
Messages postés
414
Date d'inscription
mercredi 16 juin 2004
Statut
Membre
Dernière intervention
26 juillet 2007
2
dsl pour le double post mais c'est vbfrance qui as merdouillé...
sinon ben j'ai fait plein de test comme t'as dit mais le prblm est plus compliqué que ca:
la form1 initialise la form2.
la form2 contient une textbox
la form2 contient un bouton qui lance un sub sur un module
et la fonction de ce module recupère l'info du textbox de la form2.

j'ai mis ce code dans le module:
dim formulaire2 as form2 = form2.getinstance
dim string1 as new string
string1 = formulaire2.textbox1.text
console.writeline(string1)

et ben string1 est nul, par contre, quand je mets:
dim string1 as new string
string1 = WindowsApplication1.Form2.textbox1.text
console.writeline(string1)

ca marche...
donc en fait le singleton, malgré qu'il contienne la valeur windowsapplication1.form2, n'est pas égal a windowsapplication1.form2
quand je remplace formulaire2 par windowsapplication1.form2, ca fonctionne MAIS attention! windowsapplication1.form2 ne fonctionne QUE si la fonction ne se trouve dans le meme thread que la form2.

donc voila, contrairement a ce que pourrait laisser croire visual: formulaire2 n'as pas de valeur ! (fodrait que ce soit une fonction pour que on puisse envisager de lui donner une valeur)
le singleton permet donc d'initialiser une form avec une protection multithread. Elle n'arrive pas a en recuperer l'instance dans mon cas.
quand on utilise windowsapplication1.form2, ca mets cette erreur: "Object reference not set to an instance of an object."

voila j'espere que c'est plus clair...
Messages postés
2336
Date d'inscription
samedi 14 juillet 2001
Statut
Membre
Dernière intervention
5 mai 2009
4
c'est dur de te répondre sans voir exactement le code
un petit truc quand tu es pas sur si ce que retourne le singleton est bien correct. Met toi une variable globale qui est vide en partant et dans ton new met lui une valeur.

démare ton code est fait lui un break quand tu le rappelles. Si ta varialbe globale de test est bien initialisé, il te retourne bien l'instance correctement, donc le problème viens d'ailleur. Si ta variable est vide, bien ton instance est mal créé, donc le problème viens du singleton qui doit avoir une erreur
Messages postés
414
Date d'inscription
mercredi 16 juin 2004
Statut
Membre
Dernière intervention
26 juillet 2007
2
alors en effet je me suis reinteressé plus pronfodemment (apres avoir appris bocoup sur le multithread) et finalement j'ai compris ce script plutot difficile du premier abord mais en fait plutot simple quand on le comprend. Voila, je me suis interessé de plus pres qu'avant (avec mes connaissance toute fraiche) et en fait je me rend compte que c'est abordable pour un esprit comme moi ^^, voila en fait c'est juste un script qui permet de bloquer l'evenement NEW lors d'un initialisation de form si celle si existe deja et synclock permet d'eviter que 2 multitthread fasse ensemble merder le script (utilise pour les thread mis dans des boulce appelant l'ouverture d'une form). Voila, mon probleme principal venait du fait que je croyais que .getinstance était integré au framework, finalement j'ai voulu l'utiliser hors de ta source et j'ai compris qu'en fais ce code était dans le code concepteur de la form (etant desormais dans un fichier a part dans visual 2005 ce qui est plutot chiant). Donc voila je sais comment eviter que des form s'initialise 2 fois et ceci a partir d'un thread mais j'aimerais savoir comment je peut faire pour obtenir le controle des objet sur cette meme form: je m'explique, j'ai fait un code comme ceci qui se trouve dans un thread:

dim formulaire2 as form2 = form2.getinstance
dim string1 as new string
string1 = formulaire2.label1.textbox1
console.writeline(string1)

malheuresement, il s'avere que string1 ne renvoie aucune donnée, il est vide (alors que je rempli bien le bon textbox ^^)
en clair, j'obtient: string1 = ""
donc voila, j'ai beau remplasser:
formulaire2.label1.textbox1 par form2.label1.textbox1
mais form2 n'est plus reconnu...

voila si on pouvais m'aider svp, ca m'aiderait super bien.
d'ailleur je supsonne bien que le prblm vien du fait que form2.getinstance donne pas une "redirection" vers la form2. puisque finalement, son but principal ne sert juste a initialiser ^^

@+
Lucyberad
Messages postés
117
Date d'inscription
mardi 21 janvier 2003
Statut
Membre
Dernière intervention
2 juillet 2009
1
ba... disons que mes tests sont un peu... fausses alors

J'ai fais mes tests sur Bi-Xeon 2Ghz sous 2003 Standard Edition avec 2Go de RAM (donc windows voit 4 processeurs). Ma seconde machine a des processeurs a 2,4Ghz... on ne voit pas trop la differance... ou alors ca passe trop vite pour moi (vive les joies de l'administration reseau quand on developpe aussi ;-))

De toute maniere j'envisage plutot une limitation dynamique en fonction de la charge de la machine (% de charge des processeur sur une certaine dirree limite par exemple), pour un poste client c'est plus viable.

PS: petite remarque, on observe une legere difference de performances des applis DOT NET sous 2003, mais ce n'est pas enorme contrairement a ce que dit Microsoft.
Afficher les 14 commentaires

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.