J'hésitais, mais là je suis trop tenté (même si c'est hors sujet)

Pour moi, si l'on fait du flash on doit principalement se baser sur l'API de Flash.

Dans le cas présent je prendrais la classe flash.system.SecurityDomain qui représente bien l'usage du singleton et la nécessitée du singleton dans ce cas (dans Flash) Elle ne peux être instancié : new SecurityDomain(); génère une erreur #2012: Impossible d'instancier la classe SecurityDomain. On accède au sécurity domain (le seul qui puisse exister par SWF) par le getter static SecurityDomain.currentDomain;

Si l'on ne veux pas de Singleton comme celui la (ça aurai été le cas dans un autre langage), il aurai fallut par exemple que le SecurityDomain soit apposé à l'intance root de l'application, à la class System, par sur le LoaderInfo du SWF ...

Pour le cas cité ici, je ne crois pas que faire un connection serveur en singleton soit une bonne idée, car on pourrai très bien être dans un cas ou on doit être connecté à plusieurs serveur en même temps pour faire des upload (dans le même ApplicationDomain, de toute façon on peut bien faire autant de NetConnection que l'on veux)

Pour ma part quand j'ai besoin d'un singleton j'utilise cette structure :

package example
{
        import flash.events.EventDispatcher;
        import flash.errors.IllegalOperationError;

        public class Application extends EventDispatcher
        {
                private static var _intanciateAllowed:Boolean = false;
                private static var _currentApplication:Application;
                public function Application()
                {
                        if(!_intanciateAllowed)
throw new IllegalOperationError(Error.getErrorMessage().replace("%1", Application ), 2012);//#2012: %1 class cannot be instantiated.
                }

                static public function get currentApplication():Application
                {
                        if(_currentApplication == null)
                        {
                                _intanciateAllowed = true;
                                _currentApplication = new Application();
                                _intanciateAllowed = true;
                        }
                        return _currentApplication;
                }
        }
}

Pas besoin de signature du constructeur étrange qui doit recevoir une class internal qui sert juste à ça, pas de méthode getInstance() mais juste un getter explicite et un classe entièrement accessible (du moins pour l'auto-completion).

Ceci reste un débat ouvert, vu qu'aucune règle précise en la matière n'a été dictée (par Adobe, par exemple). Mais je préfère largement qu'on garde la structure que les concepteurs de l'API de Flash on fait, ce qui permet une transition transparent entre les dev.
Par exemple en AS3 on a pas de chaining (dans l'API des DisplayObject) :
myDO.offset(50, 96).setAlpha(0.5).setWidth(500);
c'est pas la peine de l'utiliser dans des libraries même si c'est plus simple, ça rendre le code hétérogène : "ah oui ! tel libraire l'utilise, mais pas tel autre" etc. Après ça deviens un champs de bataille ou on peux faire tout et n'importe quoi.

Mais je dis ça ... je dis rien :D


Le 21/03/2011 16:36, ekameleon a écrit :
Hello :)

pour les singletons tu devrais lire :

http://code.google.com/p/maashaack/wiki/Singleton

EKA+ :)

Le 21 mars 2011 15:35, Loyat Marc<marc.lo...@gmail.com>  a écrit :

Salut,

j'ai enfin pris le temps de mettre en place le système avec fragmentation
de ByteArray. Comme le rappelait Benoit, on a besoin d'un événement
utilisateur pour l'envoi avec URLLoader, je ne vois toujours pas comment
envoyer des datas avec FileReference quand ces données ne viennent pas d'un
browse(), du coup j'ai remis en place la solution avec AMF !

Côté as3 j'ai fait un singleton pour l'envoi des fichier vers le serveur.



package
{
import com.adobe.crypto.MD5;
  import events.AMFEvent;
import flash.events.Event;
import flash.events.EventDispatcher;
  import flash.events.ProgressEvent;
import flash.utils.ByteArray;
   public class Remote extends EventDispatcher
{
  /**
  * instance unique du singleton
  */
private static var _instance:Remote;
  /**
  * geter du singleton
  * @return
  */
public static function getInstance():Remote
{
  if(_instance == null) _instance = new Remote(new PrivateRemote());
             return _instance;
}
    /**
  * lorsqu'on envoie le fichier en plein de petits morceaux,
  * on crée un identifiant unique qui permet de recoller les bouts de
l'autre côté
  */
private var _token:String;
  /**
  * numéro du morceau envoyé
  */
  private var _part:uint;
  /**
  * nombre de morceaux envoyés
  */
private var _length:uint;
  /**
  * stockage du fichier complet
  */
private var _byteArray:ByteArray;
  /**
  * nombre de bytes à prendre par tranche
  */
  private var _slice:uint = 100000;
  /**
  * les paramètres à envoyer
  */
private var _params:Object;
  private var _idMedia:int;
private var _idGabarit:int;
private var _extension:String;
  /**
  * constructeur
  * @param pvt
  */
  public function Remote(pvt:PrivateRemote):void
{
if(pvt == null){
  throw new Error("Error: Instantiation failed: Use getInstance() instead
of new.");
}
  }
  /**
  * envoi d'une déclinaison au serveur
  * @param aIdMedia
  * @param aIdGabarit
  * @param aExtension
  * @param aData
  */
  public function saveDeclinaison(aIdMedia:int, aIdGabarit:int,
aExtension:String, aData:ByteArray):void
{
  AMF.addEventListener(AMFEvent.COMPLETE, this._onComplete);
  _token = MD5.hash("t" + (new Date()).getTime() + "_" +
Math.round(Math.random() * 100000000));
_part = 0;
  _length = Math.ceil(aData.length / _slice);
_byteArray = aData;
  _idMedia = aIdMedia;
_idGabarit = aIdGabarit;
_extension = aExtension;
  _sendSlice();
  }
/**
  * envoie la partie suivante
  */
private function _sendSlice():void
{
  var vOffset:Number = _part * _slice;
var vLength:Number = vOffset + _slice>  _byteArray.length ?
_byteArray.length - vOffset : _slice;
  var vData:ByteArray = new ByteArray();
_byteArray.position = vOffset;
  _byteArray.readBytes(vData, 0, vLength);
  AMF.call('saveDeclinaison', _idMedia, _idGabarit, _extension, vData,
_token, _part, _length);
  }
   /**
  * fin du chargement
  * @param aEvent
  */
private function _onComplete(aEvent:AMFEvent):void
{
  //trace (aEvent.result);
  if (_part<  _length - 1) {
  Preloader.update(Number(_part / _length));
_part += 1;
_sendSlice();
  }
else{
Preloader.hide();
  AMF.removeEventListener(AMFEvent.COMPLETE, this._onComplete);
this.dispatchEvent(new Event(Event.COMPLETE));
  }
}
   }

}


internal class PrivateRemote {}


--------------------------
Et côté php (j'utilise le zend framework et Zend_AMF)


/**
  * sauve l'image et crée la déclinaison dans la base avec upload du fichier
en plusieurs morceaux
  * @param int $idMedia
  * @param int $idGabarit
  * @param string $extension
  * @param $aData données du fichier
  * @param string $token identificateur du fichier en cours d'upload
  * @param int $part numéro du fragment en cours d'upload
  * @param int $length nb de fragments de fichiers à uploader
   */
public function saveDeclinaison($idMedia, $idGabarit, $extension, $aData,
$token, $part, $length){
  // upload en plusieurs morceaux
         $tmpFileName = MEDIA_PATH.'/tmp'.$token;
         file_put_contents($tmpFileName, $aData, FILE_APPEND);
         if ($part == $length-1){
          $aData = file_get_contents($tmpFileName);
          unlink($tmpFileName);
        // enregistrement
$media_occ = new Default_Model_Media();
$media_occ->find($idMedia);
  $media_occ->deleteDeclinaison($idGabarit);
$media_occ->createDeclinaison($idGabarit, $extension, $aData);
         }

}

---------------------

Bon, ça marche, les utilisateurs vont être contents, mais ça fait beaucoup
d'allers/retours ! :-)


@Eka, je viens de me rendre compte que mon précédent message n'a été
adressé qu'à toi, désolé, c'était une erreur de ma part !


A+

  --
Vous recevez ce message, car vous êtes abonné au groupe Google
Groupes FCNG.
Pour envoyer un message à ce groupe, adressez un e-mail à
fcng@googlegroups.com.
Pour vous désabonner de ce groupe, envoyez un e-mail à l'adresse
fcng+unsubscr...@googlegroups.com.
Pour plus d'options, consultez la page de ce groupe :
http://groups.google.com/group/fcng?hl=fr



--
Vous recevez ce message, car vous êtes abonné au groupe Google Groupes FCNG.
Pour envoyer un message à ce groupe, adressez un e-mail à fcng@googlegroups.com.
Pour vous désabonner de ce groupe, envoyez un e-mail à l'adresse 
fcng+unsubscr...@googlegroups.com.
Pour plus d'options, consultez la page de ce groupe : 
http://groups.google.com/group/fcng?hl=fr

Répondre à