IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

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;
 
    /**
     * The User class.
     */
    public class User
    {
 
        /**
         * Creates a new User instance.
         */
        public function User( pseudo:String = null, name:String = null , address:Address = null )
        {
            this.pseudo  = pseudo ;
            this.name    = name ;
            this.address = address ;
        }
 
        /**
         * The Address reference of this object.
         */
        public var address:Address ;
 
        /**
         * The age of the user.
         */
        public var age:Number ;
 
        /**
         * The fistname of the user.
         */
        public var firstName:String ;
 
        /**
         * The job of this User.
         */
        public var job:Job ;
 
        /**
         * The mail of the user.
         */
        public var mail:String ;
 
        /**
         * The name of the User.
         */
        public var name:String ;
 
        /**
         * The pseudo of the user.
         */
        public var pseudo:String ;
 
        /**
         * The url of the User.
         */
        public var url:String ;
 
        /**
         * Destroy the user.
         */
        public function destroy():void
        {
            trace( this + " destroy.") ;
        }
 
        /**
         * Initialize the User.
         */
        public function initialize():void
        {
            trace( this + " initialize.") ;
        }
 
        /**
         * Sets the mail value of this user.
         */
        public function setMail( sMail:String ):void
        {
            mail = sMail ;
        }
 
        /**
         * Returns the string representation of the object.
         * @return the string representation of the object.
         */
        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
{
 
    /**
     * The Address class
     */
    public class Address
    {
 
        /**
         * Creates a new Address instance.
         */
        public function Address( city:String = null , street:String = null , zip:Number = NaN )
        {
            this.city    = city ;
            this.street  = street ;
            this.zip     = zip    ;
        }
 
        /**
         * The city of this address.
         */
        public var city:String ;
 
        /**
         * The street of this address.
         */
        public var street:String ;
 
        /**
         * The zip code of this address.
         */
        public var zip:Number ;
 
    }
 
}
package test
{
    import system.Reflection;
 
    /**
     * The Job class.
     */
    public class Job
    {
 
        /**
         * Creates a new Job instance.
         */
        public function Job( name:String = null )
        {
            this.name = name ;
        }
 
        /**
         * The name of this Job.
         */
        public var name:String ;
 
        /**
         * Returns the string representation of this object.
         * @return the string representation of this object.
         */
        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.

 

Valid XHTML 1.0 TransitionalValid CSS!

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.