|
|
|||||||||||
Nous allons voir comment utiliser la définition du pattern Singleton pour l'implémenter en AS3.
Définition simpliste du pattern Singleton : un objet unique et d'accès global
Notre premier réflexe c'est d'aller faire une recherche sur Google mais nous trouvons toujours une implémentation spécifique à Java hors nous sommes en Actionscript 3 (AS3).
Nous allons donc prendre en compte les spécificités du langage.
La première spécificité du langage est que nous avons un seule attribut d'accès au constructeur qui est public (specification AS3 : Constructor methods)
Ce qui peut se reveler être un problème puisqu'il faut éviter d'avoir un accès direct au constructeur, nous allons devoir trouver une solution a ce premier problème.
Voici une implémentation qui a le mérite de verrouiller l'accès au constructeur de notre Singleton :
// Logger.as package iteratif.logging { public var Logger:LoggerImpl = new LoggerImpl(); } // Nous mettons la classe à l'exterieur du package mais dans le fichier // Logger.as, cette classe est déclarée comme interne internal class LoggerImpl { private static var instancied:Boolean = false; public function LoggerImpl() { if(instancied) throw new Error ("Pattern Singleton : only one instance is permit"); instancied = true; } public function log(msg:String):void { trace(msg); } }
Nous avons le droit de mettre autant de classes internes que nous voulons dans un fichier .as, ce qui implique que nous avons uniquement accés a ces classes qu'a partir de ce même fichier.
Cette implémentation n'empêche pas la suppression de cet objet, pour y remédier nous allons déclarer Logger comme une constante :
package iteratif.logging { public const Logger:LoggerImpl = new LoggerImpl(); }
Résultat obtenu dans Flex Builder 3:
Le compilateur empêche toute compilation puisque nous tentons de supprimer une constante.
Par contre le simple fait que seul le fichier Logger.as connaît la classe LoggerImpl empêche toute forme d'héritage.
Une autre implémentation du Singleton en AS3 peut-être envisagée sans mettre la classe à l'extérieure du package mais en utilisant un metadata, a savoir le metadata [ExcludeClass].
Nous permettant si le cas se présent d'hériter du singleton :
// Fichier LoggerImpl.as package formation.iteratif.logging { [ExcludeClass] public class LoggerImpl { public function LoggerImpl() { } public function log(msg:String):void { trace(msg); } } } // Fichier Logger.as package iteratif.logging { public const Logger:LoggerImpl = new LoggerImpl(); }
Le metadata ne fait qu'exclure la classe de la complétion de code de l'éditeur Flex builder, bien entendu si vous connaissez le chemin vers cette classe, rien ne vous empêches de l'instancier.
Il est possible aussi d'utiliser le namespace internal pour réduire la visibilité d'une classe à un package, du coup plus besoin d'un metadata propre au compilateur Flex, ex :
// Fichier LoggerImpl.as package formation.iteratif.logging { internal class LoggerImpl { private static var instancied:Boolean = false; public function LoggerImpl() { if(instancied) throw new Error ("Pattern Singleton : only one instance is permit"); instancied = true; } public function log(msg:String):void { trace(msg); } } }
Cette classe est uniquement visible depuis le package formation.iteratif.logging.
Il est important de prendre en compte les spécificités du langage que vous utilisez et ce qui a été fait dans un langage ne l'est pas forcément pour un autre
(mais tellement plus facile, n'est-ce pas…).