Archive for the 'Creational patterns' Category

15
Mar

Passive Multi-View design pattern - Create Flex dynamic graphical GUIs for Flash 10 using Catalyst

Currently there is a growing need, in my opinion, to create dynamic GUIs for Rich Flash applications.
Why would you need different GUIs for the same application? There are few reasons:

  • AIR/Flex application - developing an application that will be used as Flex and AIR application, sharing the same code
  • Brands - Developing different brands for the same products
  • Multi-devices application - developing an application that will be deployed on different devices such as mobile, web and desktop

Let’s talk about multi-device applications. Currently you can develop application for different OS which can be deployed on your desktop, web or mobile device (up until today UMPC and MIDs).

Adobe announced at the GSMA Mobile World Congress that Flash Player 10 will be available on Smartphones running Windows Mobile, Google’s Android, Nokia S60 / Symbian, and Palm. Combine Flash 10 availability on many devices with the release of Flash Catalyst and you can start building applications that will be served on multiple devices. Additionally, Intel announced the optimization and enabling of Adobe Flash Player 10 and Adobe AIR on ARM which creates new possibilities for creating applications using AIR for devices such as mobile phones, set-top boxes, MIDs, TVs, automotive platforms, MP3 players and many others.

Using Flash Catalyst designer can create GUI for the developer which can be served on one device, but what if you need to create the same application for two devices with different GUIs?

One is a mobile device with smaller screen, let’s say the iPhone (which Adobe already has a version of Flash for the iPhone running on emulation software) and another one will be deployed on your home computer browser with a larger screen. You can create a custom Flex component that extends UIComponent and change the sub classes once there is a need for it, however, you may want to build a completely different GUI for each device based on the device capability. Some GUIs may not have the same sub component since you want the GUI to be lightweight to accommodate mobile development.

You can use Flash Catalyst using the State design pattern or use the presentation model (see some of my previous blogs entries). Flash Catalyst allows you to work with the new design/developer separation paradigm and support states but doesn’t allow you to create multi passive views on the same project.

Take a look at the demo project deployed using the Passive Multi-View on a Nokia MID device, UMPC device as an Adobe AIR project, as well as a laptop and desktop deployment:

Adobe Flex/AIR Cross Platform Experience

The solution: I created a new design pattern that is a mix of the Passive View design pattern as well as the Factory design pattern.
With the new design pattern you can create different views. All views are using the same base high level classes, and you can combine them easily with other tools such as: Degrafa, Flex FXG, Flex 3, AS3.0 with CSS.

I used a music service called MP3 Tunes to demonstrate the new design pattern and you can view the complete application here. After you login to your account, you can select the device size and it will show you two different GUIs based on the size you selected. This is just a POC, but in real life application you can use a context class to determine the GUI to be deployed based on user’s screen size or other factors. For instance, you can create a GUI for touch screen applications, or a GUI for Playstation.

To understand the design pattern let’s take a look at the Passive View design pattern and Factory design pattern.


Passive View Design Pattern

The Passive View pattern is a derivative of the Model View Presenter (MVP), which is considered a derivative of the Model-view-controller. The Passive View pattern has some similarities to the “Code Behind” implementation, since both achieve a complete separation of ActionScript logic and MXML or AS component tags. The passive presentation model allows us to easy test our application since we can create test cases just for the logic and if needed test cases for the view
In passive view pattern we split our laundry to two piles, view and presenter:

View
* State is in the view
* View is passive and is not aware of the Presenter
Presenter
* Logic is in the Presenter.
* Presenter observes view events.
* Presenter updates the view data.
* Presenter ‘knows’ about the components in the view.
* Presenter holds the data or point to a data class.

By moving all the logic out of the view, the Passive View pattern can achieve the separation of designer and developer work and create a paradigm where it’s easy to change the view. The view class contains only the components and their states, no events, logic, changes or model. This pattern works great with Flash Catalyst since the designer responsibility is to create the view (pixel) and behavior (state) so you can copy/paste the FXG code into the application and just set the id’s of each component.

Passive View Flex UML

Factory Design Pattern
Now throw in the mix the factory design pattern and you can actually create few views for each presenter.
The factory pattern is one of the most basic creational patterns that deals with the problem of creating different products without specifying the exact concrete class that will be created. This is done by by creating a separate method for creating the product abstract class, whose subclasses can override to specify the derived type of product that will be created. The best way to describe that is to think of a pizza restaurant that holds different types of Pizza such as Mushroom pizza, Bacon pizza and other types of pizza, however, they are all pizzas that include the same ingredients such as dough, cheese and others.

Factory Design Pattern UML

Now if we mix these two design patterns together we get the following UML diagram. The Creator uses the factory pattern to find out which view (product) to use and then takes that and pushes it into the presenter. The Sub-presenter and subView can be used by the main view.

UML-multi-view-passive-view-factory

Now let’s put it to work and look at the working example with some screen shots. The application creator let you decide which view to use:

mp3tunes flex application

Once a view is selected, the presenter is provided with the view and creates the GUI:
mp3tunes flex application smaller

mp3tunes flex application larger

The screen shot is of an application I created in Illustrator, converted it to Flash Catalyst and then imported it to Flex.
Let’s take a look at the Factory Class. The class holds two constants for each product and the “AbstractMusicPlayerMain” allows us to be able to select different products that extends that class.


package com.elad.mp3tunes.view
{
	import com.elad.mp3tunes.view.mobile.MusicPlayerMain320x480;
	import com.elad.mp3tunes.view.web.MusicPlayerMain530x520;

	import flash.errors.IllegalOperationError;

	public final class MusicPlayerFactory
	{
		/**
		 * Music player types enums
		 */
		public static const WEB:int = 0;
		public static const MOBILE:int = 1;

		public static function createView(musicPlayerType:Number):AbstractMusicPlayerMain
		{
			var retVal:AbstractMusicPlayerMain;

			switch (musicPlayerType)
			{
				case WEB:
					retVal = new MusicPlayerMain530x520();
				break;
				case MOBILE:
					retVal = new MusicPlayerMain320x480();
				break;
				throw new IllegalOperationError("The view type " + musicPlayerType + " is not recognized.");
			}

			return retVal;
		}
	}
}

The abstract class holds all the components that will be used by presenter, take a look:


package com.elad.musicplayer.view
{
	import com.elad.framework.musicplayer.Player;
	import mx.components.baseClasses.FxComponent;
	import mx.components.baseClasses.FxScrollBar;
	import mx.containers.Canvas;
	import mx.controls.ProgressBar;
	import mx.graphics.graphicsClasses.TextGraphicElement;

	public class AbstractMusicPlayer extends Canvas
	{
		private var player:Player = new Player();

		// text
		public var songInfoText:TextGraphicElement;
		public var currentTimeText:TextGraphicElement;
		public var totalTimeText:TextGraphicElement;

		// Buttons
		public var playButton:FxComponent;
		public var pauseButton:FxComponent;
		public var forwardButton:FxComponent;
		public var rewindButton:FxComponent;
		public var randomButton:FxComponent;
		public var replyButton:FxComponent;
		public var artistsButton:FxComponent;
		public var albumsButton:FxComponent;

		// sliders
		public var songSlider:FxScrollBar;
		public var trackProgressBar:ProgressBar;
		public var downloadProgressBar:ProgressBar;
		public var volumeProgressBar:ProgressBar;
		public var volumeSlider:FxScrollBar;

		public function AbstractMusicPlayer()
		{
			super();
		}
	}
}

The product is each main view mxml class. Keep in mind that the MXML classes allow us to implements interfaces but not to extends a class, the closest way to extend a class is to use the abstract class in the main tag instead of let’s say the Canvas tag. Using that will use the class constructor, which typically is against how abstract is created. Once we repeat the same component they will be overriding the abstract class members;


<view:AbstractMusicPlayer xmlns="http://ns.adobe.com/mxml/2009"
	xmlns:lib="MusicPlayerSmall_library.*"
	xmlns:d="http://ns.adobe.com/fxg/2008/dt"
	xmlns:th="http://ns.adobe.com/thermo/2009"
	xmlns:ai="http://ns.adobe.com/ai/2008"
	xmlns:view="com.elad.musicplayer.view.*"
	backgroundColor="0xe6e6e6"
	width="320" height="480"
	horizontalScrollPolicy="off"
	verticalScrollPolicy="off"
	borderStyle="solid" borderThickness="3">

		<!-- Track Slider -->
		<Group>
			<ProgressBar id="downloadProgressBar"
				left="37" top="84"
				barSkin="com.elad.musicplayer.view.mobile.components.DownloadProgressBarSkin"
				trackSkin="com.elad.musicplayer.view.mobile.components.DownloadProgressTrackSkin"
				minimum="0" maximum="100"
				labelWidth="0"
				direction="right" mode="manual" />
			<ProgressBar id="trackProgressBar" alpha="0.5"
				left="37" top="84"
				barSkin="com.elad.musicplayer.view.mobile.components.TrackProgressBarSkin"
				trackSkin="com.elad.musicplayer.view.mobile.components.TrackProgressTrackSkin"
				minimum="0" maximum="100"
				labelWidth="0"
				direction="right" mode="manual" />
			<FxHScrollBar id="songSlider" left="32" top="72"
				skinClass="com.elad.musicplayer.view.mobile.components.HorizontalScrollbar1"/>
		</Group>

</view:AbstractMusicPlayer>

The presenter handles the logic of the main application, as well as using sub presenter and sub view if needed.


package com.elad.musicplayer.view.presenter
{
	import com.elad.mp3tunes.Music;
	import com.elad.mp3tunes.enum.SortType;
	import com.elad.mp3tunes.events.AlbumDataEvent;
	import com.elad.mp3tunes.events.ArtistsResultEvent;
	import com.elad.mp3tunes.events.TrackDataEvent;
	import com.elad.mp3tunes.vo.AlbumItemVO;
	import com.elad.mp3tunes.vo.AlbumListVO;
	import com.elad.mp3tunes.vo.ArtistItemVO;
	import com.elad.mp3tunes.vo.ArtistListVO;
	import com.elad.mp3tunes.vo.TrackItemVO;
	import com.elad.mp3tunes.vo.TrackListVO;
	import com.elad.musicplayer.view.AbstractMusicPlayerMain;
	import flash.events.Event;
	import mx.collections.ArrayCollection;
	import mx.controls.Alert;
	import mx.events.ListEvent;

	/**
	 * Presentation Pattern - Passive View
	 *
	 * @author Elad
	 *
	 */
	 [Bindable]
	public class MusicPlayerMainPresenter
	{

	    //--------------------------------------------------------------------------
	    //
	    //  Variables
	    //
	    //--------------------------------------------------------------------------
		private var music:Music = Music.getInstance();
		private var artistList:ArtistListVO = null;
		private var albumList:AlbumListVO = null;
		private var trackList:TrackListVO = null;
		private var tileResultType:String;

		// Corresponding view
		private var musicPlayerMain:AbstractMusicPlayerMain;

        // Sub-presenters
        private var musicPlayerPresenter:MusicPlayerPresenter;

	    //--------------------------------------------------------------------------
	    //
	    //  Constructor
	    //
	    //--------------------------------------------------------------------------
		public function MusicPlayerMainPresenter(musicPlayerMain:AbstractMusicPlayerMain)
		{
			this.musicPlayerMain = musicPlayerMain;
			musicPlayerPresenter = new MusicPlayerPresenter(musicPlayerMain.musicPlayer);
			musicPlayerMain.dg.addEventListener(Event.CHANGE, dgChangeHandler);
			musicPlayerMain.tileList.addEventListener(Event.CHANGE, selectTileListItem);
			musicPlayerMain.musicPlayer.addEventListener(MusicPlayerPresenter.NEXT_TRACK_EVENT, nextTrack);
			musicPlayerMain.musicPlayer.addEventListener(MusicPlayerPresenter.PREVIOUS_TRACK_EVENT, previousTrack);
			musicPlayerMain.musicPlayer.addEventListener(MusicPlayerPresenter.ARTISTS_CLICK_EVENT, getAllArtists);
			musicPlayerMain.musicPlayer.addEventListener(MusicPlayerPresenter.ALBUMS_CLICK_EVENT, getAllAlbums);
			musicPlayerMain.musicPlayer.addEventListener(MusicPlayerPresenter.PLAYING_COMPLETED, function():void { nextTrack(null); } );
			getAllArtists();
		}

	    //--------------------------------------------------------------------------
	    //
	    //  Class methods
	    //
	    //--------------------------------------------------------------------------

		private function nextTrack(event:Event):void
		{
			var trackItem:TrackItemVO = trackList.getItem(++musicPlayerMain.dg.selectedIndex);
			musicPlayerPresenter.playSong(trackItem);
		}

		private function previousTrack(event:Event):void
		{
			var trackItem:TrackItemVO = trackList.getItem(--musicPlayerMain.dg.selectedIndex);
			musicPlayerPresenter.playSong(trackItem);
		}

		private function getAllAlbums(event:Event=null):void
		{
			music.addEventListener(AlbumDataEvent.ALL_ALBUMS_DATA_COMPLETED, onAllAlbumCompleted);
			music.getAllAlbums(artistList);
		}

		private function getAllArtists(event:Event=null):void
		{
			music.addEventListener(ArtistsResultEvent.ARTIST_RESULT_COMPLETED, onArtistsResult);
			music.addEventListener(ArtistsResultEvent.ARTIST_RESULT_ERROR, function(event:ArtistsResultEvent):void { Alert.show(String(event.message)); });
			music.getMusicByArtists();
		}

	    //--------------------------------------------------------------------------
	    //
	    //  Event handlers
	    //
	    //--------------------------------------------------------------------------
		protected function selectTileListItem(event:ListEvent):void
		{
			var index:Number = event.columnIndex;
			getTrackList(index);
		}

		protected function getTrackList(index:Number):void
		{
			var id:String;
			music.addEventListener(TrackDataEvent.TRACK_DATA_COMPLETED, onTrackDataComplete);
			music.addEventListener(TrackDataEvent.TRACK_DATA_ERROR, function():void { Alert.show("Error getting track data"); });
			// based on the type in the tile list
			switch (tileResultType)
			{
				case SortType.ALBUMS:
					var albumItem:AlbumItemVO = albumList.getItem(index);
					id = albumItem.albumId;
				break
				case SortType.ARTISTS:
					var artistItem:ArtistItemVO = artistList.getItem(index);
					id = artistItem.artistId;
				break
			}
			music.getTrackData(id, tileResultType);
		}

		protected function dgChangeHandler(event:ListEvent):void
		{
			var index:Number = event.rowIndex;
			var trackItem:TrackItemVO = trackList.getItem(index);
			musicPlayerPresenter.playSong(trackItem);
		}

		private function onArtistsResult(event:ArtistsResultEvent):void
		{
			music.removeEventListener(ArtistsResultEvent.ARTIST_RESULT_COMPLETED, onArtistsResult);
			tileResultType = SortType.ARTISTS;
			artistList = new ArtistListVO(event.artistList.list.source);
			var item:ArtistItemVO = artistList.getItem(0);
			var dp:ArrayCollection = new ArrayCollection();
			for (var i:Number = 0; i<artistList.list.length; i++)
			{
				item = artistList.getItem(i);
				dp.addItem({name: item.artistName, count: item.trackCount});
			}
			musicPlayerMain.tileList.dataProvider = dp;
			musicPlayerMain.tileList.selectedIndex = 0;
			getTrackList(0);
		}

		private function onAllAlbumCompleted(event:AlbumDataEvent):void
		{
			music.removeEventListener(AlbumDataEvent.ALL_ALBUMS_DATA_COMPLETED, onAllAlbumCompleted);
			tileResultType = SortType.ALBUMS;
			albumList = new AlbumListVO(event.collection.list.source);
			var item:AlbumItemVO;
			var dp:ArrayCollection = new ArrayCollection();
			for (var i:Number = 0; i<albumList.list.length; i++)
			{
				item = albumList.getItem(i);
				dp.addItem({name: item.albumTitle, count: item.trackCount});
			}
			musicPlayerMain.tileList.dataProvider = dp;
			musicPlayerMain.tileList.selectedIndex = 0;
			getTrackList(0);
		}

		private function onAlbumDataComplete(event:AlbumDataEvent):void
		{
			music.removeEventListener(AlbumDataEvent.ALBUM_DATA_COMPLETED, onAlbumDataComplete);
			music.removeEventListener(AlbumDataEvent.ALBUM_DATA_ERROR, onAlbumDataComplete);
			var albumList:AlbumListVO = new AlbumListVO(event.collection.list.source);
			var albumId:String = albumList.getItem(0).albumId;
			music.addEventListener(TrackDataEvent.TRACK_DATA_COMPLETED, onTrackDataComplete);
			music.addEventListener(TrackDataEvent.TRACK_DATA_ERROR, function():void { Alert.show("Error getting track data"); });
			music.getTrackData(albumId);
		}

		private function onTrackDataComplete(event:TrackDataEvent):void
		{
			music.removeEventListener(AlbumDataEvent.ALBUM_DATA_COMPLETED, onAlbumDataComplete);
			music.removeEventListener(TrackDataEvent.TRACK_DATA_ERROR, function():void { Alert.show("Error getting track data"); });
			trackList = new TrackListVO(event.collection.list.source);
			// show track list
			musicPlayerMain.dg.dataProvider = trackList.list.source;
			// play first song
			var trackItem:TrackItemVO = trackList.getItem(0);
			musicPlayerPresenter.playSong(trackItem);
			// set selected song
			musicPlayerMain.dg.selectedIndex = 0;
		}
	}
}

The creator then takes both the product and the presenter and create a composition:


var musicPlayerView:AbstractMusicPlayerMain = MusicPlayerFactory.createView(type);
this.addChild(musicPlayerView);
musicPlayerMainPresenter = new MusicPlayerMainPresenter(musicPlayerView);

see complete of the creator:


<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
	backgroundColor="0xe6e6e6"
	x="0" y="0"
	verticalAlign="middle"
	creationComplete="creationCompleteHandler(event)">
	<mx:Style source="assets/css/main.css" />
	<mx:Script>

		<![CDATA[
			import com.elad.musicplayer.view.presenter.MusicPlayerMainPresenter;
			import com.elad.musicplayer.view.AbstractMusicPlayerMain;
			import com.elad.musicplayer.view.LoginForm;
			import mx.managers.PopUpManager;
			import mx.containers.TitleWindow;
			import mx.events.FlexEvent;
			import com.elad.musicplayer.view.MusicPlayerFactory;
			import com.elad.musicplayer.view.AbstractMusicPlayerMain;
            private var loginForm:LoginForm;
			private var musicPlayerMainPresenter:MusicPlayerMainPresenter;
			// handler after creation complete
			protected function creationCompleteHandler(event:FlexEvent):void
			{
				loginForm = LoginForm(PopUpManager.createPopUp(this, LoginForm, true));
				loginForm.addEventListener(LoginForm.LOGIN_SUCCESSFULL, onLogin);
			}

			// method to load the view
			protected function loadView(type:Number):void
			{
				hBox.visible = false;
				hBox = null;
				var musicPlayerView:AbstractMusicPlayerMain = MusicPlayerFactory.createView(type);
				this.addChild(musicPlayerView);
				musicPlayerMainPresenter = new MusicPlayerMainPresenter(musicPlayerView);
			}

			private function onLogin(event:Event):void
			{
				hBox.visible = true;
			}
		]]>
	</mx:Script>

	<mx:HBox id="hBox" visible="false">
		<mx:Button label="320x480" click="loadView(MusicPlayerFactory.MOBILE)" />
		<mx:Button label="530x520" click="loadView(MusicPlayerFactory.WEB)" />
	</mx:HBox>

</mx:Application>

To view the complete application Click here.
Please note that you have to have an account with MP3tunes Music Locker in order to login into your account and use the application.

23
Mar

Use singletons discreetly. Here are some tips to help you decide when to use the singleton pattern.

Singleton design pattern should be used discreetly. Many of us are building API’s and using singletons as a means to create a global object that can be accessed across the application.Here’s why you should use singleton discreetly:

  1. In many cases, using singleton is an anti-pattern;
  2. The singleton may be considered as an anti Action Script, since Action Script 3.0 doesn’t support private or protected constructor;
  3. With programming, it is usually not recommended to

use global objects, since it is hard to test them and the developer has to make assumptions regarding the application and how they will be used.

The main source of the problems is that using the singleton pattern makes the classes tightly coupled instead of loosely coupled, meaning that you can only test a few classes together rather than each of the classes at a time, as you should.

Before I go into a discussion on when is it a good idea to use the singleton pattern, I think it’s a good idea to show how the singleton is used in Action Script 3.0.

What is the singleton pattern?
The singleton pattern is used to restrict instantiation of a class to one object. The pattern keeps a private constructor to insure that the class was created only once.

Singleton in Action Script 3.0:
Action script does not support the option to declare constructor as private or protected inside of a package, which causes a design pattern problem, since any option you choose will be considered workaround or a “hack”.

One popular option is to use the inner classes, meaning creating another class inside of the package to behave as the private constructor, such as in the example below:

package {

	public class Manager
	{
		/**
		 * var to be used by the singleton pattern to return the instance of the class.
		 */
		private static var manager : Manager;

		/**
		 * Internal constructor. Should not be called from outside this class.
		 *
		 * @param enforcer	Enforce the creation of one class only.
		 *
		 */

		public function Manager(enforcer:AccessRestriction)
		{
			// TODO: throw exception
			if ( enforcer == null )
			{
				throw new Error("Manager error enforcer input param is undefined" );
			}
		}

		/**
		 * Method function to retrieve instance of the class
		 *
		 * @return The same instance of the class
		 *
		 */
		public static function getInstance() : Manager
		{
			if( manager == null )
				manager = new Manager(new AccessRestriction());

			return manager
		}
	}
}

class AccessRestriction {}

To view the source code as text file click here.

So when should you use the singleton design pattern?
Here’s a singleton recommended check list:

  1. Singleton should be used in cases where only one object is needed to coordinate actions and/or events across the application;
  2. The application will always use the object in the same way;
  3. It doesn’t really matter to the client what’s going on in the rest of the application, meaning that the singleton object is independent.

If you can confirm the check list, than it’s a good candidate to use the singleton pattern.

Have fun designing!

15
Mar

Boost Flex performance with Object Pooling Manager API

Object Pooling Manager API is an open source API that allows you to create a collection of objects and use them at any given time. These usable objects can be anything from a UI component to an XML list. The Object Pooling manager ensures the management of the collections of objects and allows the client to keep using them without costing any additional resources.

Flex is a single thread programming language which means that the program cannot split itself into more than one simultaneously tasks and it causes flex to slow down, especially when the cost of initializing a class is high. Object pooling can be used to manage object caching and boost performance.

A real life example is a book case. You have a case full of books and you decide to read one of the books. While you use the book you may stained a page by a coffee and changed the look of the book. After you are done using the book you return the book to the book case for later usage.

Object pooling works the same way, the object pooling class is singleton to insure you are not pulling more than one reusable object at a time. At any given time you pick a reusable object, the object is being removed from the collection so the client can change it and place it back for future usage.

The Flex API I developed is based on creating a usable collection of objects, the objects can be any component such as Flex Sprite or Canvas, array, class or anything you want it to be.

The object pooling can boost performance; especially in cases where the resources used to initializing a class instance are high, the number of times the class will be usage is often, and the number of instantiations in use at any single time is low.

All source code contained in this API has been published under the MIT licence and is protected as stated therein.

To see an example and download source code:
http://elromdesign.com/blog/Flex/API/ObjectPoolManager/

To view the ASDOC of all the API:
http://elromdesign.com/blog/Flex/API/asdoc/

Object Pooling UML

03
Mar

Custom cursor API is a great solution for creating sets of custom cursors

Custom cursor API is a great solution for creating sets of custom cursors. Each set is a concrete class that you can set. In addition, you can implement custom events such as: mouse down, mouse up and custom busy cursor.

CursorManager class is useful for replacing the cursor with a custom cursor or for creating a busy cursor, but what do you do when you want to create a set of custom cursors? You may also be interested in building few sets of custom cursors to be used in different part of the application and keep track of them in one centralized location.
For example you want to create couple of sets of cursors. One of them will be a custom image, the cursor will change on mouse down and mouse up events and the cursor will have a custom busy image. That set will be used in one component and another set will be used in a different component.

Custom cursor API is based on creating custom sets of cursors for usage in an application. You create a concrete class and set all the images, swf or sprite objects you want to assign to that set and the cursor will change according to how you set it in the concrete class.

All source code contained in this API has been published under the MIT licence and is protected as stated therein.

To see an example and download source code:
http://elromdesign.com/blog/Flex/API/Cursor/

To view the ASDOC of the API:
http://elromdesign.com/blog/Flex/API/asdoc/

Cursor UML Class diagram

21
Feb

SQLStatements Manager API will generate SQL commands for forms and other UI interactions.

Building a large Flex application that communicates with a remote server through SQL commands create an architect design problem. What do you do with all the SQL commands? Do you store them in a properties file or create 50-100 ColdFusion files? What do you do once you want to change some of these SQL commands?

The issue gets even worse once you need to submit few SQL commands for one operation. For example you have a form and once that form submit the client request to sign to a newsletter so you would need two SQL statements.

I created an elegant solution to that problem, utilizing the Abstract Method design pattern. The “SQLStatements Manager” (Flex SQL statements API) will let you create different CRUD (Create, Read, Update and Delete) statements for each form and you have one place where all your SQL commands are located so once it’s time to change them or update your database design, you don’t have to go through your entire application looking for all these SQL statements.

Once you have the SQL statement you can submit them to the database in order to process. I may give an example of implementation of the API using ColdFusion and Cairngorm.

To see an example and download source code:
http://elromdesign.com/blog/Flex/API/SQLStatementsManager/

To view the ASDOC of the API:
http://elromdesign.com/blog/Flex/API/asdoc/

This API will be in a new Flex 3.0 book I am writing called “Developing Enterprise Architect Applications.” click here to read more and pre-order.

All source code contained on this page has been published under the MIT license and is protected as stated therein.

SQLStatments Manager

15
Feb

Display different file types using FileViewer, factory pattern open source API

The API is responsible for displaying different files type. There are many scenarios where you want your application to use a different class or component to display different types of files. You can use “if-else” statements; however the problem is when you want to use different type of component or classes to handle the different types of files. Using the factory design pattern solve that problem; The concrete product needs to implements the “IView” interface and the component that is responsible for displaying the file can be of any type. “UIFileViewer” class is responsible for creating the component and adding it to the UIComponent.

This API will be in a new Flex 3.0 book I am writing called “Developing Enterprise Architect Applications.” click here to read more and pre-order.

All source code contained on this page has been published under the MIT licence and is protected as stated therein.

FileViewer UML

To see an example and download the source code click here:
http://elromdesign.com/blog/Flex/API/FileViewer/

ASDOC:
http://elromdesign.com/blog/Flex/API/asdoc/