VEGAS - Design Pattern d'inversion de contrôle : Définitions d'objets
Date de publication : 11/09/2009
I. Introduction
I-A. Résumé des différentes parties de ce chapitre et des attributs qui seront traités à l'interieur.
I-A-1. Les attributs de base d'une définition d'objet
I-A-2. Cycle de vie d'un objet configuré avec une définition d'objet
I-A-3. Les différentes stratégies utilisées par la fabrique pour créer un objet avec une définition d'objet
I-A-4. L'attribut "evaluators"
I-B. Exemple général de cet article
I. Introduction
Nous avons vu dans l'
article précédent que les conteneurs
IoC contiennent des
définitions d'objet qui sont des "
modes d'emploi" qui permettent de créer des objets dans une application. Elles définissent aussi les relations de dépendances que peuvent avoir les objets et les classes les uns avec les autres.
Dans le modèle IoC de AndromedAS, Les définitions d'objets sont représentées par des objets qui implémentent l'interface IObjectDefinition, cette interface est implémentée par la classe ObjectDefinition.
L'interface IObjectDefinition possède les caractéristiques suivantes :
- Un identifiant unique pour chaque définition d'objet (obligatoire).
- Une description du type de l'objet qui sera renvoyé ou créé avec la définition d'objet (obligatoire).
- Les références vers les dépendances ( ou collaborateurs ) de l'objet.
- Tous les éléments qui permettront d'initialiser l'objet au moment de sa création.
- Tous les éléments qui permettront de contrôler le comportement d'un objet dans l'application : scope de l'objet, méthodes invoquées tout au long de son cycle de vie, etc.
Les concepts énumérés ci-dessus correspondent à un ensemble d'éléments contenus dans des objets génériques simples qui permettent de créer et d'initialiser les définitions d'objet d'un conteneur IoC.
La classe ObjectDefinition contient une méthode statique create(init:Object) qui lui permet de générer des nouvelles instances très simplement en passant en paramètre un objet générique d'initialisation compatible avec les attributs qui seront définis par la suite dans ce chapitre. En général il sera toujours plus simple d'utiliser cette méthode que d'initialiser à la main toutes les instances de types ObjectDefinition d'un conteneur IoC.
Exemple : Créer une définition d'objet avec un objet d'initialisation dynamique simple |
import flash. text . TextField ;
import flash. text . TextFormat ;
import andromeda. ioc. core. ObjectDefinition ;
var init: Object =
{
id : " my_field " ,
type : " flash.text.TextField " ,
singleton : true ,
properties :
[
{ name : " defaultTextFormat " , value : new TextFormat (" verdana " , 11 ) } ,
{ name : " selectable " , value : false } ,
{ name : " text " , value : " hello world " }
]
}
var definition: ObjectDefinition = ObjectDefinition. create ( init ) ;
trace ( " definition.id : " + definition. id ) ;
trace ( " definition.getType() : " + definition. getType () ) ;
trace ( " definition.getScope() : " + definition. getScope () ) ;
trace ( " definition.isSingleton() : " + definition. isSingleton () ) ;
trace ( " definition.isLazyInit() : " + definition. isLazyInit () ) ;
trace ( " definition.getProperties() : " + definition. getProperties () )
|
Ces objets génériques contiennent différents attributs. Nous allons étudier ces attributs dans 4 parties distinctes.
I-A. Résumé des différentes parties de ce chapitre et des attributs qui seront traités à l'interieur.
I-A-1. Les attributs de base d'une définition d'objet
Aller directement à cette partie
I-A-2. Cycle de vie d'un objet configuré avec une définition d'objet
Aller directement à cette partie
I-A-3. Les différentes stratégies utilisées par la fabrique pour créer un objet avec une définition d'objet
Aller directement à cette partie
I-A-4. L'attribut "evaluators"
Aller directement à cette partie
I-B. Exemple général de cet article
Nous allons définir pour la suite de l'article un exemple de base qui illustrera comment définir une collection (Array) d'objets génériques qui servirons à initialiser une fabrique IoC. Cette collection pourra par la suite être stockée dans un fichier texte externe au format eden ou directement dans le code source ActionScript de l'application.
Prenons le temps de créer une petite classe test.User, cette classe permet d'illustrer les dépendances que peut avoir une classe avec d'autres classes.
La classe test.User |
package test
{
import system. Reflection;
public class User
{
public function User ( pseudo: String = null , name : String = null , address: Address = null )
{
this . pseudo = pseudo ;
this . name = name ;
this . address = address ;
}
public var address: Address ;
public var age: Number ;
public var firstName: String ;
public var job: Job ;
public var mail: String ;
public var name : String ;
public var pseudo: String ;
public var url : String ;
public function destroy (): void
{
trace ( this + " destroy. " ) ;
}
public function initialize (): void
{
trace ( this + " initialize. " ) ;
}
public function setMail ( sMail: String ): void
{
mail = sMail ;
}
public override function toString (): String
{
return " [ " + Reflection. getClassName (this ) + ( pseudo ! = null ? " " + pseudo : " " ) + " ] " ;
}
}
}
|
Nous observons dans la classe test.User les notions de dépendances expliquées dans le chapitre précédent au niveau de sa fonction constructeur, ses attributs et ses méthodes.
La classe test.User possède de nombreuses dépendances, nous pourront noter en particulier une dépendance avec les classes test.Address et test.Job définies ci-dessous :
La classe test.Address |
package test
{
public class Address
{
public function Address ( city: String = null , street: String = null , zip: Number = NaN )
{
this . city = city ;
this . street = street ;
this . zip = zip ;
}
public var city: String ;
public var street: String ;
public var zip: Number ;
}
}
package test
{
import system. Reflection;
public class Job
{
public function Job ( name : String = null )
{
this . name = name ;
}
public var name : String ;
public override function toString (): String
{
return " [ " + Reflection. getClassName (this ) + " " + name + " ] " ;
}
}
}
|
Voyons maintenant un exemple de configuration IoC contenant l'ensemble des définitions d'objet au format ECMASCript (objets génériques) qui permettra ensuite d'initialiser un conteneur léger IoC et de créer un objet de type test.User :
objects =
[
{
id : " address " ,
type : " test.Address " ,
properties :
[
{ name : " city " , value : " Marseille " } ,
{ name : " street " , value : " xx xxx xxxxxxxxxxx " } ,
{ name : " zip " , value : 13001 }
]
}
,
{
id : " job_dev " ,
type : " test.Job " ,
scope : " prototype " ,
properties : [ { name : " name " , value: " AS Developper " } ]
}
,
{
id : " user " ,
type : " test.User " ,
arguments :
[
{ value : " eKameleon " } ,
{ value : " ALCARAZ " } ,
{ ref : " address " }
] ,
lazyInit : true ,
singleton : true ,
destroy : " destroy " ,
init : " initialize " ,
properties :
[
{ name : " age " , value : 31 } ,
{ name : " firstName " , value : " Marc " } ,
{ name : " job " , ref : " job_dev " } ,
{ name : " url " , value : " http://www.ekameleon.net " }
{ name : " setMail " , arguments : [ { value : " ekameleon [at] gmail.com " } ] }
]
}
] ;
|
L'exemple précédent n'utilise pas tous les attributs définis au début de ce chapitre mais illustre les fonctionnalités les plus importantes d'une définition d'objet.
Il ne reste plus qu'à initialiser la fabrique IoC et récupérer l'objet de type test.User défini dans celle-ci dans un bout de code ActionScript très simple :
import andromeda. ioc. factory. ECMAObjectFactory ;
import test. User ;
var factory: ECMAObjectFactory = ECMAObjectFactory. getInstance () ;
factory. create ( objects ) ;
var user: User = factory. getObject ( " user " ) as User ;
trace ( user ) ;
|
Nous utiliserons en grande partie cet exemple dans les descriptions des attributs qui vont suivre même si, parfois, il nous faudra sortir des sentiers battus pour expliquer avec d'autres exemples certaines notions importantes.
Copyright © 2009 test.
Aucune reproduction, même partielle, ne peut être faite
de ce site ni de l'ensemble de son contenu : textes, documents, images, etc.
sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à
trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.