Dev (Back & Front)ARTIGO

Criando sistemas reais com Flex – Parte 03

Leia os artigos anteriores:

Criando sistemas reais com Flex – Parte 02

Criando sistemas reais com Flex – Parte 01

*

Hoje vamos aprender a usar um pouco de padrão de projetos no desenvolvimento de sistemas em Flex. A idéia básica é mostrar que é possível utilizar qualquer tipo de padrão existente durante o desenvolvimento de aplicações RIA. 

Um padrão de projeto, resumidamente, define uma solução em relação a um problema no desenvolvimento de sistemas. Existem diversos padrões, você pode consultar no Google por “design patterns” para saber mais sobre eles.

De todos os padrões existentes um dos mais usados é o Factory Method (http://pt.wikipedia.org/wiki/Factory_Method). Neste link da Wikipedia existe toda a definição formal deste padrão, não sendo necessário explicá-lo novamente. Bom, se você leu o link e não entendeu muito, tudo bem, respire fundo e continue a ler nosso artigo, pois vou explicar o padrão com um exemplo em Flex, o que é muito mais fácil, ok ?

Tendo em mente que um Design Pattern aborda a solução de um problema, vamos inicialmente falar sobre o problema. Imagine que você está utilizando as janelas MDI do artigo anterior. Você criou dezenas de janelas (cada janela é um componente mxml) e agora, dado um menu em XML, você deseja abrir estas janelas.

Então, no seu código, você faz algo assim:

<?xml version="1.0" encoding="utf-8"?><br /><mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" xmlns:code="http://code.google.com/p/flexlib/"<br />	paddingBottom="0" paddingLeft="0" paddingRight="0" paddingTop="0"<br />	><br /><br /><mx:Style source="WindowsClassic.css"/>     <br /><br /><mx:MenuBar width="100%" labelField="@label" id="MyMenuBar"            itemClick="OnClickMenu(event)"><br /><mx:XMLList><br /><menuitem label="File"><br />	<menuitem label="Open" /><br />	<menuitem label="Save" /><br />	<menuitem label="Exit" /><br /></menuitem><br /><menuitem label="Edit"><br /><menuitem label="Cut"/><br /><menuitem label="Copy"/><br /><menuitem label="Paste"/><br /></menuitem><br /></mx:XMLList><br /></mx:MenuBar><br /><br /><code:MDICanvas  id="MDI"  width="100%" height="100%"><br /><br /></code:MDICanvas><br /><br /><mx:Script><br />	<![CDATA[<br />		import mx.controls.Alert;<br />		import mx.events.MenuEvent;<br /><br />private function OnClickMenu(event:MenuEvent):void<br />		{<br />			if (event.label == "Open")<br />			{<br />				//Abrir janela Open<br />			}<br /><br />			if  (event.label == "Save")<br />			{<br />				//Abrir janela Save<br />			}<br /><br />			// ... E mais 100 Ifs.......<br /><br />		}<br /><br />	]]><br /></mx:Script><br /><br /></mx:Application>

A parte mais crítica deste código está em vermelho. É uma função que é executada quando escolhemos um item do menu. Ou seja, quando escolhemos um item, devemos necessariamente abrir uma janela MDI. Então, dependendo do Label, eu iria abrir a janela correspondente.

Quando nosso menu chegasse a 100 itens, teríamos 100 ifs! Seria uma seqüência interminável. Seria muito ruim isso não seria??? Por que? Porque iria deixar o código longo de mais, e muito repetido. Suponha que um mês após criar os ifs, você tenha que validar algo, ou criar algo diferente, tendo a necessidade de alterar cada if em questão. Então, este é o problema!!

Para resolver esse tipo de problema (muitos ifs), podemos dizer que o padrão Factory Method irá nos ajudar. A sua característica básica é criar uma classe que servirá de classe base para todas as telas do sistema. O nosso sistema conhecerá apenas a classe base, e não as outras classes (janelas MDI). Somente quando a aplicação estiver rodando, as classes que herdam da nossa classe base serão acessadas. Resumindo, temos que somente as subclasses serão instanciadas, e não a classe base.

Bom, talvez seja difícil de explicar com poucas palavras. Um exemplo é muito melhor. Inicialmente vamos criar a nossa classe base. Ela é a classe base de todas as janelas MDI do sistema. Então iremos chamá-la de MDIWindowBase.

No Adobe Flex, acione o menu File, New, ActionScript Class:

Inicialmente o código da classe é o seguinte:

package windows<br />{<br />	import flexlib.mdi.containers.MDIWindow;<br /><br />	public class MDIWindowBase extends MDIWindow<br />	{<br />		public function MDIWindowBase()<br />		{<br />			super();<br />		}<br /><br />	}<br />}

Esta classe base poderá conter métodos e funcionalidades que serão comuns a todas as janelas do sistema. Como estamos criando um sistema “real”, temos que prever certas situações que possam ocorrer no futuro. Esta previsão resulta na criação de classes que, a princípio, não possuem uma funcionalidade definida.

Após criar a classe base, vamos criar a interface que irá garantir que as janelas que iremos criar possuem uma espécie de contrato a seguir. Na orientação a objetos, uma interface pode ser facilmente explicada como um contrato em papel. Pense assim, um contrato de locação de imóveis contém diversas regras claras, tais como pagar o aluguel até o dia 5 de cada mês, não fazer barulho após às 22 horas etc. Um contrato na orientação a objetos é uma interface que possui métodos que deverão ser implementados pelas classes que implementarem a respectiva interface.

Vamos criar uma interface chamada IMDIWindow.

Esta interface possui inicialmente o seguinte código:

package windows<br />{<br />	import flexlib.mdi.containers.MDIWindow;<br /><br />	public class MDIWindowBase extends MDIWindow<br />	{<br />		public function MDIWindowBase()<br />		{<br />			super();<br />		}<br /><br />	}<br />}

Vamos incluir um método chamado “GetName” nesta interface. Com isso, todo objeto que implementa esta interface deverá possuir o método “GetName”.

package windows<br />{<br />	public interface IMDIWindow<br />	{<br />		function GetName():String;<br />	}<br />}

Agora que criamos a classe base, e a Interface, podemos criar a nossa primeira janela MDI. Ela se chamará Janela01.

O código dela será:

<?xml version="1.0" encoding="utf-8"?><br /><MDIWindowBase xmlns="windows.*" <br />	xmlns:mx="http://www.adobe.com/2006/mxml" width="400" height="300"<br />	title="Janela 01"<br />	implements="windows.IMDIWindow"<br />	><br /><br />	<mx:Script><br />		<![CDATA[<br /><br /><br />		public function GetName():String<br />		{<br />			return "Janela01";<br />		}	<br /><br /><br /><br /><br />		]]><br />	</mx:Script><br /><br /></MDIWindowBase>

Veja que incluímos a propriedade Implements e criamos o método GetName, da Interface (IMDIWindow). Podemos criar mais 2 janelas neste esquema. Nosso projeto é algo do tipo:

Ainda falta uma terceira classe, que pode ou não ser criada. Ela se chama MDIWindowHelper e contém funções de manipulação das janelas MDI. Eu estou isolando as funções de manipulação das janelas nesta classe, ao invés de colocá-las no arquivo principal do projeto.

Este helper conterá um array com todas as janelas. Quando clicarmos em um item de menu, iremos perguntar ao Helper qual janela deverá ser aberta, e ele irá devolvê-la. O arquivo Helper possui o seguinte código:

package windows<br />{<br />	import mx.collections.ArrayCollection;<br /><br />	public class MDIWindowHelper<br />	{<br /><br />		protected var Windows : ArrayCollection;<br /><br />		public function MDIWindowHelper()<br />		{<br />			Windows = new ArrayCollection();<br /><br />			Windows.addItem(new Janela01());<br />			Windows.addItem(new Janela02());<br />			Windows.addItem(new Janela03());<br /><br /><br /><br />		}<br /><br />		public function GetWindow( name:String):MDIWindowBase<br />		{<br />			for each (var w : IMDIWindow in Windows)<br />			{<br />				if (w.GetName() == name)<br />					return w as MDIWindowBase; <br />			}		<br />			return null;<br />		}<br /><br /><br />	}<br />}

Para finalizar, a aplicação principal fica com o seguinte código:

<?xml version="1.0" encoding="utf-8"?><br /><mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" xmlns:code="http://code.google.com/p/flexlib/"<br />	paddingBottom="0" paddingLeft="0" paddingRight="0" paddingTop="0"<br />	creationComplete="OnCreationComplete(event)"<br />	><br /><br /><mx:Style source="WindowsClassic.css"/>     <br /><br /><mx:MenuBar width="100%" labelField="@label" id="MyMenuBar" itemClick="OnClickMenu(event)"><br /><mx:XMLList><br /><menuitem label="<strong>Window</strong>"><br />	<menuitem label="<strong>Janela01</strong>" /><br />	<menuitem label="<strong>Janela02</strong>" /><br />	<menuitem label="<strong>Janela03</strong>" /><br /></menuitem><br /><menuitem label="Edit"><br /><menuitem label="Cut"/><br /><menuitem label="Copy"/><br /><menuitem label="Paste"/><br /></menuitem><br /></mx:XMLList><br /></mx:MenuBar><br /><br /><code:MDICanvas  id="MDI"  width="100%" height="100%"><br /><br /></code:MDICanvas><br /><br /><mx:Script><br />	<![CDATA[<br />		import windows.MDIWindowBase;<br />		import flexlib.containers.WindowShade;<br />		import windows.MDIWindowHelper;<br />		import mx.controls.Alert;<br />		import mx.events.MenuEvent;<br /><br />		private var WindowHelper: MDIWindowHelper;<br /><br />		protected function OnCreationComplete(event:Event):void<br />		{<br /><strong>WindowHelper = new MDIWindowHelper();</strong><br />		}<br /><br />		private function OnClickMenu(event:MenuEvent):void<br />		{<br /><strong>var w:MDIWindowBase = WindowHelper.GetWindow(event.label);</strong><br /><strong>			if (w != null)</strong><br /><strong>				MDI.addChild(w);</strong>			<br />		}<br /><br />	]]><br /></mx:Script><br /><br /></mx:Application>

As partes em negrito são as mais importantes. Aqueles if do início foram substituídos pela classe Helper, que tenta pegar de sua lista de janelas, a janela correta. Para poder saber o nome da janela, o Helper usa o contrato (interface) IMDIWindow, executando o método GetName() de cada classe existente no array.

Quando formos criar a Janela04, devemos criá-la implementando a interface IMDIWindow e devemos adicioná-la na lista de janelas do MDIHelper. Lembre-se de que o nome retornado no método GetName deve ser o mesmo presente no Label do item de menu da aplicação principal.

Aguardo o feedback de vocês! Abraços !

trabalha com desenvolvimento web desde 1998 e atualmente dedica-se a escrever livros sobre programação e desenvolvimento de sistemas, disponíveis no seu site.

Ver perfil