La notion de Plugin, le multi-MVC dans Pixlib

Comme nous l’avons vu lors de la découverte du MVC dans Pixlib. Le core de Pixlib structure les projets Flash sous la forme d’un MVC+FC, où chaque modèle, vue et commande possède un identifiant unique. Ces identifiants permettent de cibler ces derniers de manière globale dans une application Pixlib.

Le souci avec cette gestion globale du MVC est qu’il est très risqué de charger plusieurs « projets Pixlib » dans une même application (risque de télescopage au niveau des identifiants). Apparu avec lowRA (Pixlib v2), le Plugin permet de supprimer cette limitation !

Un plugin == un owner == un channel

Un plugin est égal à l’encapsulation d’un MVC+FC (composé de n modèles, n vues, n commandes + FrontController et d’PXPluginChannel).

On retrouve dans chaque instance de la classe PXAbstractPlugin (ou interface PXPlugin), une instance de PXModelLocator, PXViewLocator et PXFrontController lier au plugin. Le plugin est utilisé comme un filtre au niveau des Locators,  par ce biais, les identifiants utilisés pour récupérer les PXModel, PXView et PXCommand sont uniques seulement au sein d’une instance de PXAbstractPlugin. Plus de souci donc, si deux modèles utilisent le même identifiant, du moment qu’ils sont instanciés dans deux plugins différents.

public class MyPlugin extends PXAbstractPlugin
{
	override protected function initialize() : void
	{
		super.initialize();
 
		var view : PXView = new MyView(this, "MyView");
		var model : MyModel = new MyModel(this, "MyModel");
		controller.pushCommandClass("onCheck", CheckCommand);
	}
}

En pratique, lors de l’instanciation d’un PXModel ou d’une PXView, on donne comme valeur à la propriété owner l’instance du plugin auquel elle appartient. Implicitement, le modèle ou la vue va automatiquement s’enregistrer auprès du bon Locator.

Pour récupérer une de mes instances

PXModelLocator.getInstance(MyPluginInstance).locate("MyModel");
PXViewLocator.getInstance(MyPluginInstance).locate("MyView");

Communication entre plugins

Pouvoir faire tourner plusieurs MVC dans une même application c’est bien, pouvoir les faire communiquer entre eu c’est mieux!

À l’instar de la méthode firePrivateEvent qui permet d’envoyer un événement au PXFrontController du plugin. Il existe deux méthodes au sein de la classe PXAbstractPlugin pour communiquer avec les plugins voisins.

La méthode firePublicEvent, qui permet d’envoyer un événement à tous les plugins abonnés au plugin émetteur via l’une des deux méthodes : addPluginListeneraddPluginEventListener.

La méthode fireExternalEvent quant à elle permet de cibler un plugin receveur en prenant en 2e argument le PXPluginChannel du plugin cible.

// Main

var pluginB : PXPlugin = new PluginB();
var pluginC : PXPlugin = new PluginC();
 
var pluginA : PluginA = new PluginA();
pluginA.addPluginListener(pluginB);
pluginA.addPluginEventListener("onShout", pluginC);
pluginA.talk();
pluginA.shout();
pluginA.kill(pluginC.channel);

// PluginA

public class PluginA extends PXAbstractPlugin
{
	public function PluginA()
	{
		registerInternalChannel(this);
		// only use for non IoC context
		super();
	}
 
	public function talk() : void
	{
		firePublicEvent(new PXStringEvent("onTalk", this, "Hello I'm Plugin A"));
	}
 
	public function shout() : void
	{
		firePublicEvent(new PXStringEvent("onShout", this, "I'm Plugin A and I'm nervous !"));
	}
 
	public function kill(channel : PXEventChannel) : void
	{
		fireExternalEvent(new PXStringEvent("onKill", this, "I'm Plugin A and I Want kill you !"), channel);
	}
}

// PluginB

public class PluginB extends PXAbstractPlugin
{
	public function PluginB()
	{
		registerInternalChannel(this);
		// only use for non IoC context
		super();
	}
 
	public function onTalk(event : PXStringEvent) : void
	{
		logger.debug("I receive a message : " + event.value, this);
	}
}

// PluginC

public class PluginC extends PXAbstractPlugin
{
	public function PluginC()
	{
		registerInternalChannel(this);
		// only use for non IoC context
		super();
	}
 
	public function onShout(event : PXStringEvent) : void
	{
		logger.debug(event.value, this);
	}
 
	public function onKill(event : PXStringEvent) : void
	{
		logger.debug(event.value, this);
	}
}

Important, lors de l’extension de la classe PXAbstractPlugin pour un usage non IOC, il est important d’appeler la méthode registerInternalChannel(this); afin de pouvoir définir le PXPluginChannel du plugin.

À l’image du PXEventChannel dans l’API de logging, le PXPluginChannel sert de « canal de diffusion » propre au MVC du plugin.

 

Retrouvez les sources de l’exemple sur la page de téléchargement du Google code.

 

Happy coding with Pixlib

This entry was posted in Core, Framework, Tutorial. Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="" cssfile="">