<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>masputih &#187; OOP</title>
	<atom:link href="http://masputih.com/category/as3/oop/feed" rel="self" type="application/rss+xml" />
	<link>http://masputih.com</link>
	<description>Coder for Hire</description>
	<lastBuildDate>Mon, 24 May 2010 08:48:37 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Factory Pattern</title>
		<link>http://masputih.com/2009/05/factory-pattern</link>
		<comments>http://masputih.com/2009/05/factory-pattern#comments</comments>
		<pubDate>Wed, 06 May 2009 10:53:00 +0000</pubDate>
		<dc:creator>Anggie Bratadinata</dc:creator>
				<category><![CDATA[ActionScript 3]]></category>
		<category><![CDATA[Design Patterns]]></category>
		<category><![CDATA[OOP]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[actionscript]]></category>
		<category><![CDATA[pattern]]></category>

		<guid isPermaLink="false">http://masputih.com/?p=354</guid>
		<description><![CDATA[Factory Pattern adalah pattern yang digunakan untuk memisahkan (decouple) proses pembuatan/instansiasi sebuah objek (produk) dari objek lain (klien) yang menggunakannya. Tujuannya supaya perubahan pada product class nggak menyebabkan kita harus mengubah kode pada client. Paling nggak akibat dari perubahan itu bisa diminimalisir. Dan juga supaya si factory bisa digunakan oleh banyak class. Factory adalah objek [...]]]></description>
			<content:encoded><![CDATA[<p></p><p><em>Factory Pattern</em> adalah pattern yang digunakan untuk memisahkan (<em>decouple</em>) proses pembuatan/instansiasi sebuah objek (produk) dari objek lain (klien) yang menggunakannya. Tujuannya supaya perubahan pada <em>product class</em> nggak menyebabkan kita harus mengubah kode pada <em>client</em>. Paling nggak akibat dari perubahan itu bisa diminimalisir. Dan juga supaya si <em>factory</em> bisa digunakan oleh banyak class.</p>
<p><em>Factory</em> adalah objek yang berfungsi membuat objek lain (produk). Class ini menyembunyikan proses pembuatan produk dari klien sehingga klien nggak perlu tahu proses pembuatannya, bahkan klien juga nggak perlu tahu nama class dari produk yang dia minta.</p>
<p>Mungkin kita sering menulis function seperti ini: </p>
<pre class="codeblock">
<code>
var coffee:AbstractCoffee = createCoffee("xxx");
function createCoffee(type:String):Coffee{
        if(type == "xxx" ) return new XXXCoffee();
        if(type == "yyy" ) return new YYYCoffee();
        if(type == "zzz" ) return new ZZZCoffee();
        return null;
}</code>
</pre>
<p>Cukup bagus untuk proyek kecil. Tapi coba bayangin kalo kita punya 20 class yang harus bisa bikin kopi dan semuanya harus bisa ditukar-tukar saat <em>run-time</em> plus si produk kemungkinan besar bakal berubah. Repot. Di sini gunanya Factory Pattern.</p>
<p><span id="more-354"></span></p>
<p>Factory Pattern memungkinkan instansiasi sebuah produk didelegasikan ke subclass (<em>concrete factory</em>) dari <em>base-class</em> yang bersifat generik (abstrak) . Keuntungannya adalah si klien hanya perlu tau generik classnya, jadi <em>concrete factory</em> bisa ditukar-tukar secara dinamis (polymorfis) tergantung produk apa yang dibutuhkan dan klien nggak perlu tau detil pembuatan produk.</p>
<div id="attachment_353" class="wp-caption aligncenter" style="width: 300px">
	<a href="http://masputih.com/2009/05/factory-pattern/factory-methodjpg" rel="attachment wp-att-353"><img src="http://masputih.com/uploads/2009/05/factory-method-300x32.jpg" alt="Diagram Dasar Factory" title="factory-method.jpg" width="300" height="32" class="size-medium wp-image-353" /></a>
	<p class="wp-caption-text">Diagram Dasar Factory</p>
</div>
<p>Ada 2 varian factory pattern yaitu :</p>
<ol>
<li>Factory Method</li>
<li>Abstract Factory</li>
</ol>
<h3>Factory Method (FM)</h3>
<blockquote><p>Define an interface for creating an object, but let the subclasses decide which class to instantiate. The Factory method lets a class defer instantiation to subclasses. (wikipedia)</p>
<p>Factory Method is similar to Abstract Factory but without the emphasis on families. (sourcemaking.com)</p>
</blockquote>
<div id="attachment_360" class="wp-caption aligncenter" style="width: 300px">
	<a href="http://masputih.com/2009/05/factory-pattern/factorymethod-class-diagram" rel="attachment wp-att-360"><img src="http://masputih.com/uploads/2009/05/factorymethod-class-diagram-300x221.jpg" alt="Factory Method" title="factorymethod-class-diagram" width="300" height="221" class="size-medium wp-image-360" /></a>
	<p class="wp-caption-text">Factory Method</p>
</div>
<p>Dalam <em>Factory Method</em>, setiap <em>concrete factory</em> bertugas membuat satu produk. Jadi ada pemetaaan 1–1 antara <em>factory</em> dan produk yang dibuatnya. Klien menggunakan <em>abstract factory</em> untuk membuat objek tapi jenis objek itu ditentukan oleh <em>concrete factory</em> yang dipilih.</p>
<p>Contoh:</p>
<pre class="brush:as3">
public class Main extends Sprite{

	public var factory:AbstractFactory;
	public var product:AbstractProduct;

	public function Main():void{

		factory = new ABCFactory();
		product = factory.createProduct();

		factory = new DEFFactory();
		product = factory.createProduct();

		factory = new XYZFactory();
		product = factory.createProduct();

	}
}

//abstract factory
public class AbstractFactory {

	public function AbstractFactory() {}

	public function createProduct():AbstractProduct {
		throw new IllegalOperationError("Abstract method. Must be implemented in subclass");
		return null;
	}

}

//abstract product
public class AbstractProduct {
	public function AbstractProduct() {}
}

//concrete factories
public class ABCFactory extends AbstractFactory {
	override public function createProduct():AbstractProduct {
		return new ProductABC();
	}
}
public class DEFFactory extends AbstractFactory {
	override public function createProduct():AbstractProduct {
		return new ProductDEF();
	}
}

//concrete products
public class ProductABC extends AbstractProduct{
	public function ProductABC() {
		trace("ProductABC created");
	}
}

public class ProductDEF extends AbstractProduct {
	public function ProductDEF() {
		trace("ProductDEF created");
	}
}
</pre>
<p>Output:</p>
<pre class="codeblock"><code>
ProductABC created
ProductDEF created

</code></pre>
<p>Dalam contoh di atas, kalo class ProductABC berubah, misalnya konstruktornya harus kita beri parameter “id”, kita nggak perlu utak-atik class Main. Cukup kita modifikasi ABCFactory. Contohnya gini :</p>
<pre class="brush:as3">
public class ProductABC extends AbstractProduct{
	public function ProductABC(id:String) {
		trace("ProductABC created with id " + id);
	}
}

public class ABCFactory extends AbstractFactory {
	override public function createProduct():AbstractProduct {
		var id:String = String(Math.round(Math.random() * 10));
		return new ProductABC(id);
	}
}
</pre>
<pre class="codeblock"><code>
ProductABC created with id 8
ProductDEF created

</code></pre>
<h3>Abstract Factory (AF)</h3>
<blockquote><p>The intent in employing the pattern is to insulate the creation of objects from their usage. This allows for new derived types to be introduced with no change to the code that uses the base class. (wikipedia)</p>
<p>Abstract Factory emphasizes a family of product objects. (sourcemaking.com)</p>
</blockquote>
<div id="attachment_361" class="wp-caption aligncenter" style="width: 300px">
	<a href="http://masputih.com/uploads/2009/05/abstract-factory-class-diagram.jpg" rel="shadowbox"><img src="http://masputih.com/uploads/2009/05/abstract-factory-class-diagram-300x203.jpg" alt="Abstract Factory" title="abstract-factory-class-diagram" width="300" height="203" class="size-medium wp-image-361" /></a>
	<p class="wp-caption-text">Abstract Factory</p>
</div>
<p>Perbedaan utama antara Abstract Factory dengan Factory Method adalah dalam pemetaan antara <em>factory</em> dengan produk. Dalam AF, satu factory bisa membuat banyak produk yang sekelompok.</p>
<p>Biar lebih gampang dipahami, saya buat aplikasi sederhana berikut ini.</p>
<h3>Demo : Warung Factory</h3>
<div class="wp-caption aligncenter" style="width: 295px">
	<a href="http://labs.masputih.com/patterns/abstractfactory/index.html" rel="shadowbox"><img alt="Click to see the demo" src="http://labs.masputih.com/patterns/abstractfactory/screenshot.jpg" title="Warung Factory" width="295" height="244" /></a>
	<p class="wp-caption-text">Click to see the demo</p>
</div>
<div id="attachment_384" class="wp-caption aligncenter" style="width: 300px">
	<a href="http://masputih.com/2009/05/factory-pattern/warung" rel="attachment wp-att-384"><img src="http://masputih.com/uploads/2009/05/warung-300x224.jpg" alt="Class Diagram" title="warung" width="300" height="224" class="size-medium wp-image-384" /></a>
	<p class="wp-caption-text">Class Diagram</p>
</div>
<div class="box dl_box">Project files : <a href="http://masputih.com/wordpress/wp-content/plugins/download-monitor/download.php?id=abstractfactory.rar" title="Downloaded 468 times">→ AbstractFactory.rar</a></div>
<h4>Factory</h4>
<pre class="brush:as3">package factory {

	import product.AbstractProduct;
	import flash.errors.IllegalOperationError;

	public class AbstractFactory {

		public function AbstractFactory(name:String) {
			trace("Pesan makanan/minuman di " + name);
		}

		public function createProduct(type:String):AbstractProduct {
			throw new IllegalOperationError("Abstract method. Must be implemented in subclass.");
		}

		public function getProducts():Array {
			throw new IllegalOperationError("Abstract method. Must be implemented in subclass.");
		}

	}

}
</pre>
<p>Berikut ini turunannya, yaitu concrete factory yang akan membuat produk berdasarkan pilihan menu.</p>
<pre class="brush:as3">
//WarungBuTini.as
package factory {
	import product.AbstractProduct;
	import product.NasiRawon;
	import product.KopiSusu;
	import product.SodaGembira;

	public class WarungBuTini extends AbstractFactory{

		public static const NAME:String = "Warung Bu Tini";

		public function WarungBuTini() {
			super(NAME);
		}

		override public function createProduct(type:String):AbstractProduct {

			if (type == SodaGembira.NAME) return new SodaGembira(NAME,"4500");
			if (type == NasiRawon.NAME) return new NasiRawon(NAME, "8000");
			if (type == KopiSusu.NAME) return new KopiSusu(NAME, "6000");

			throw Error("Invalid product type");
			return null;
		}

		override public function getProducts():Array {
			return [SodaGembira.NAME,NasiRawon.NAME,KopiSusu.NAME];
		}

	}

}

//DepotAgung.as
package factory {
	import product.AbstractProduct;
	import product.NasiGoreng;
	import product.PangsitMie;
	import product.SodaGembira;

	public class DepotAgung extends AbstractFactory{

		public static const NAME:String = "Depot Agung";

		public function DepotAgung() {
			super(NAME);
		}

		override public function createProduct(type:String):AbstractProduct {
			if (type == NasiGoreng.NAME) return new NasiGoreng(NAME, "5500");
			if (type == PangsitMie.NAME) return new PangsitMie(NAME, "4000");
			if (type == SodaGembira.NAME) return new SodaGembira(NAME, "3000");

			throw Error("Invalid product type");
			return null;
		}

		override public function getProducts():Array {
			return [NasiGoreng.NAME,PangsitMie.NAME,SodaGembira.NAME];
		}

	}

}
</pre>
<h4>Product</h4>
<pre class="brush:as3">package product {
	import flash.display.Sprite;
	import flash.text.TextField;

	public class AbstractProduct extends Sprite{

		//timeline objects
		public var productName:TextField;
		public var price:TextField;
		public var factoryName:TextField;

		public function AbstractProduct(productName:String,price:String,factoryName:String) {
			this.productName.text = productName;
			this.price.text = "Rp " + price;
			this.factoryName.text = factoryName;
			trace("Beli " + productName + " di " + factoryName);
		}

		public function pay():void{
			trace("Bayar " + price.text + " ke " + factoryName.text);
		}

	}

}
</pre>
<p>Concrete Factory akan membuat objek dari concrete product dan mengirimkannya ke klien ( <code>Main</code> )<br />
Berikut ini <em>concrete product </em>nya</p>
<pre class="brush:as3">
//NasiGoreng.as
package product {

	[Embed(source='../assets/assets.swf', symbol='NasGor')]
	public class NasiGoreng extends AbstractProduct {

		public static const NAME:String = "Nasi Goreng";

		public function NasiGoreng(factoryName:String,price:String = "7000") {
			super(NAME,price,factoryName)
		}

	}

}

//SodaGembira.as
package product {

	[Embed(source='../assets/assets.swf', symbol='Sogem')]
	public class SodaGembira extends AbstractProduct {

		public static const NAME:String = "Soda Gembira";

		public function SodaGembira(factoryName:String,price:String = "5000") {
			super(NAME, price, factoryName);
		}

	}

}
</pre>
<h4>Main class</h4>
<pre class="brush:as3">package
{
	import factory.AbstractFactory;
	import factory.DepotAgung;
	import factory.WarungBuTini;
	import factory.WarungPakJaja;
	import product.AbstractProduct;
	import fl.controls.ComboBox;
	import fl.controls.List;
	import flash.display.Sprite;
	import flash.events.Event;

	public class Main extends Sprite{

		public function Main():void{
			if (stage) init();
			else addEventListener(Event.ADDED_TO_STAGE, init);
		}

		private var _productPic:Sprite;
		private var _selector:FactorySelector;

		//main class hanya pakai base/abstract class, bukan concrete class
		private var _factory:AbstractFactory;
		private var _product:AbstractProduct;

		private function init(e:Event = null):void {
			removeEventListener(Event.ADDED_TO_STAGE, init);

			//_factory &#038; _products _selector
			_selector = new FactorySelector();
			addChild(_selector);

			_selector.factories.addEventListener(Event.CHANGE, selectFactory);
			_selector.productList.addEventListener(Event.CHANGE, onProductChange);

			_selector.factoryData = [WarungBuTini.NAME, DepotAgung.NAME];

			//product picture holder
			_productPic = new Sprite();
			_productPic.x = 10;
			_productPic.y = _selector.height + 20;
			addChild(_productPic);

		}

//----------------------------------------------------------- FACTORY SELECTION

		private function selectFactory(e:Event = null):void {

			switch(_selector.factories.selectedLabel) {
				case WarungBuTini.NAME:
					_factory = new WarungBuTini();
				break;
				case DepotAgung.NAME:
					_factory = new DepotAgung();
				break;
			}

			_selector.productData = _factory.getProducts();
		}

//----------------------------------------------------------- PRODUCT SELECTION

		private function onProductChange(e:Event):void {
			var type:String = _selector.productList.itemToLabel(_selector.productList.selectedItem);
			_product = _factory.createProduct(type);
			_product.pay();

			setPicture(_product);
		}

//----------------------------------------------------------- DISPLAY PRODUCT IMAGE		

		private function setPicture(product:AbstractProduct):void {

			var i:int = _productPic.numChildren;
			while (i--) {
				_productPic.removeChildAt(i);
			}

			_productPic.addChild(product);
		}
	}
}
</pre>
<h4>Tambah Factory &amp; Produk Baru</h4>
<p>Kalo kita ingin buat factory baru, langkah-langkahnya adalah :</p>
<ol>
<li>Buat sub-class dari AbstractFactory</li>
<li>Sub-class itu harus punya konstanta bernama <code>NAME</code> yang dipakai untuk menampilkan nama factory di dalam combobox</li>
<li>Override <code>createProduct()</code> dan <code>getProducts()</code></li>
<li>Tambahkan ke daftar factory
<pre class="codeblock"><code>_selector.factoryData = [...,..., FactoryBaru.NAME];</code></pre>
</li>
<li>Instansiasi factory di dalam  <code>selectFactory()</code>
<pre class="codeblock"><code>switch(_selector.factories.selectedLabel) {
	....
	case FactoryBaru.NAME:
		_factory = new FactoryBaru();
	break;
}
</code></pre>
</li>
</ol>
<p>Untuk bikin produk baru:</p>
<ol>
<li>Buat subclass dari <code>AbstractProduct </code>dengan <em>parameterized constructor</em> dan konstanta <code>NAME</code>
<pre class="codeblock"><code>
public static const NAME:String = "Produk Baru";
public function ProdukBaru(factoryName:String,price:String = "7000") {
	super(NAME,price,factoryName)
}

</code></pre>
</li>
<li>Daftarkan nama produk di dalam factory pembuatnya, lihat <code>getProducts()</code>
<pre class="codeblock"><code>override public function getProducts():Array {
	return [...,...,ProdukBaru.NAME];
}
</code></pre>
</li>
<li>Instansiasi produk di dalam <code>createProduct()</code>
<pre class="codeblock"><code>override public function createProduct(type:String):AbstractProduct {
	...
	if (type == ProdukBaru.NAME) return new ProdukBaru(NAME,"1200");
	...
}</code></pre>
</li>
</ol>
<p>Contoh:</p>
<p>Produk baru : Kopi Susu</p>
<pre class="brush:as3">
[Embed(source='../assets/assets.swf', symbol='Tarik')]
public class KopiSusu extends AbstractProduct {

	public static const NAME:String = "Kopi Susu";

//----------------------------------------------------------- INIT

	public function KopiSusu(factoryName:String,price:String = "3500") {
		super(NAME, price, factoryName);

	}

}
</pre>
<p>Factory baru : Warung Pak Jaja. Salah satu dagangannya adalah Kopi Susu.</p>
<pre class="brush:as3">
public class WarungPakJaja extends AbstractFactory {

	public static const NAME:String = "Warung Pak Jaja";

//----------------------------------------------------------- INIT

	public function WarungPakJaja() {
		super(NAME);
	}

	override public function createProduct(type:String):AbstractProduct {

		if (type == KopiSusu.NAME) return new KopiSusu(NAME,"1200");
		if (type == SodaGembira.NAME) return new SodaGembira(NAME, "3000");
		if (type == NasiGoreng.NAME) return new NasiGoreng(NAME, "7500");

		throw Error("Invalid product type");
		return null;
	}

	override public function getProducts():Array {
		return [KopiSusu.NAME,SodaGembira.NAME,NasiGoreng.NAME];
	}

}
</pre>
<p>Tambahkan Warung Pak Jaja ke dalam Main class :</p>
<pre class="brush:as3">
private function init(e:Event = null):void {
	removeEventListener(Event.ADDED_TO_STAGE, init);

	//_factory &#038; _products _selector
	_selector = new FactorySelector();
	addChild(_selector);

	_selector.factories.addEventListener(Event.CHANGE, selectFactory);
	_selector.productList.addEventListener(Event.CHANGE, onProductChange);

	_selector.factoryData = [WarungBuTini.NAME, WarungPakJaja.NAME, DepotAgung.NAME];

	//product picture holder
	_productPic = new Sprite();
	_productPic.x = 10;
	_productPic.y = _selector.height + 20;
	addChild(_productPic);

}

//----------------------------------------------------------- FACTORY SELECTION

private function selectFactory(e:Event = null):void {

	switch(_selector.factories.selectedLabel) {
		case WarungPakJaja.NAME:
			_factory = new WarungPakJaja();
		break;
		case WarungBuTini.NAME:
			_factory = new WarungBuTini();
		break;
		case DepotAgung.NAME:
			_factory = new DepotAgung();
		break;
	}

	_selector.productData = _factory.getProducts();
}
</pre>
<p>Di output panel :</p>
<pre class="codeblock"><code>
Pesan makanan/minuman di Warung Bu Tini
Beli Kopi Susu di Warung Bu Tini
Bayar Rp 6000 ke Warung Bu Tini
Pesan makanan/minuman di Depot Agung
Beli Pangsit Mie di Depot Agung
Bayar Rp 4000 ke Depot Agung
Pesan makanan/minuman di Warung Pak Jaja
Beli Soda Gembira di Warung Pak Jaja
Bayar Rp 3000 ke Warung Pak Jaja
Beli Kopi Susu di Warung Pak Jaja
Bayar Rp 1200 ke Warung Pak Jaja

</code></pre>
<p>Di dalam arsip project file di atas, saya ada banyak produk yang bisa Anda pakai untuk utak atik.</p>
<p>Oke, sekian artikel tentang Factory Method &amp; Abstract Factory. Mudah-mudahan bermanfaat. Kalo nggak ngerti silakan tanya.</p>
<h3>Links</h3>
<ul>
<li>Project file : <a href="http://masputih.com/wordpress/wp-content/plugins/download-monitor/download.php?id=abstractfactory.rar" title="Downloaded 468 times">→ AbstractFactory.rar</a></li>
<li><a href="http://www.sourcemaking.com">sourcemaking.com</li>
<li><a href="http://www.as3dp.com">www.as3dp.com</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://masputih.com/2009/05/factory-pattern/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MVC Sederhana untuk Pemula</title>
		<link>http://masputih.com/2009/05/mvc-sederhana-untuk-pemula</link>
		<comments>http://masputih.com/2009/05/mvc-sederhana-untuk-pemula#comments</comments>
		<pubDate>Fri, 01 May 2009 08:30:57 +0000</pubDate>
		<dc:creator>Anggie Bratadinata</dc:creator>
				<category><![CDATA[ActionScript 3]]></category>
		<category><![CDATA[OOP]]></category>
		<category><![CDATA[Repost]]></category>
		<category><![CDATA[actionscript]]></category>
		<category><![CDATA[pattern]]></category>

		<guid isPermaLink="false">http://masputih.com/?p=119</guid>
		<description><![CDATA[Repost artikel yg sudah pernah saya posting di blog yang lama. Kali ini saya jelaskan tentang cara membuat “struktur” MVC sederhana untuk menulis kode yang maintainable dengan memecah kode menjadi beberapa bagian berdasarkan fungsinya ( separation of concerns ). Saya anggap Anda sudah cukup mengetahui dasar OOP dan mempraktekkannya, jadi saya nggak perlu menjelaskan lagi [...]]]></description>
			<content:encoded><![CDATA[<p></p><blockquote><p>Repost artikel yg sudah pernah saya posting di <a href="http://old.masputih.com">blog yang lama</a>. </p></blockquote>
<p>Kali ini saya jelaskan tentang cara membuat “struktur” MVC sederhana untuk menulis kode yang maintainable dengan memecah kode menjadi beberapa bagian berdasarkan fungsinya ( <em>separation of concerns</em> ).</p>
<p>Saya anggap Anda sudah cukup mengetahui dasar OOP dan mempraktekkannya, jadi saya nggak perlu menjelaskan lagi apa itu <em>class</em>, <em>instance</em>, <em>static</em>, <em>getter/setter</em>, dsb. Saya juga nggak menjelaskan apa itu <em>custom events</em> dan bagaimana cara membuat &amp; menggunakannya karena sudah pernah saya jelaskan dalam artikel yang lain. Selain itu, Anda juga harus mengerti cara mendefinisikan &amp; membuat <em>custom class</em> untuk objek di <em>library</em>.</p>
<p><span id="more-119"></span></p>
<p>Di sini saya membuat aplikasi sederhana berupa sebuah kotak yang posisinya bisa dikontrol oleh 4 tombol seperti berikut:</p>
<div class="swfcontainer" style="text-align:center">
<div class="swf" style="margin:10px;border:1px solid #ccc;">
[kml_flashembed fversion=“9.0.124″ movie=“http://masputih.com/files/SimpleMVC.swf” targetclass=“flashmovie” publishmethod=“static” width=“320” height=“400”]</p>
<p><a href="http://adobe.com/go/getflashplayer"><img src="http://www.adobe.com/images/shared/download_buttons/get_flash_player.gif" alt="Get Adobe Flash player" /></a></p>
<p>[/kml_flashembed]
</p></div>
</div>
<h3>Design Patterns</h3>
<p><em>Design patterns</em> (DP) adalah sekumpulan solusi generik untuk masalah-masalah yang umum ditemui oleh para <em>developer</em> dalam membuat aplikasi. <em>Pattern</em> berarti pola, artinya DP bukan berupa kode, tetapi berupa panduan yang implementasinya terserah <em>developer</em> yang menggunakannya.</p>
<p>Info yang lebih lengkap bisa Anda baca di <a href="http://id.wikipedia.org/wiki/Pola_desain">wikipedia</a>.</p>
<h3>Model-View-Controller</h3>
<p>MVC adalah <em>meta-pattern</em> , artinya <span class="caps">MVC</span> bukan merupakan <em>pattern</em> yang berdiri sendiri tapi merupakan kumpulan dari beberapa <em>pattern</em> &amp; dalam buku <em>Head First Design Patterns</em> , MVC dimasukkan dalam kelompok <em>compound-pattern</em>.</p>
<p>Pada prinsipnya, implementasi MVC membagi kode ke dalam 3 bagian yaitu:</p>
<ul>
<li>Model sebagai sumber data</li>
<li>View sebagai representasi data dan <em>user interface</em></li>
<li>Controller yang berfungsi sebagai “otak” atau <em>business logic</em> yang memproses <em>user input</em> dan meng–<em>update</em> Model dan View ( kalau diperlukan ).</li>
</ul>
<h4>Apa keuntungan <span class="caps">MVC </span>?</h4>
<p>Sekilas MVC kelihatannya merepotkan karena kita harus menulis kode lebih banyak tapi keuntungannya adalah kode kita lebih <em>maintainable</em> karena kita bisa mengubah salah satu bagian tanpa harus mengubah bagian yang lain. Sebagai contoh, misalnya kita membuat aplikasi A yang memproses data berformat XML namun kemudian kita diharuskan menggunakan data berformat JSON. Dalam kasus seperti ini, kita cukup mengubah Model tanpa harus mengubah bagian yang lain.</p>
<p>MVC juga mempermudah <em>debugging</em> karena kita bisa memperkirakan bagian mana yang bermasalah tanpa harus membongkar seluruh kode yang sudah kita buat.</p>
<p>Jadi secara umum, keuntungan MVC jauh lebih besar daripada kerepotan yang ditimbulkannya. Di samping itu, kalo Anda nggak mau repot menulis berbaris-baris kode, mungkin menjadi <em>programmer</em> bukan profesi yang cocok buat Anda &amp; sebaiknya Anda <a href="http://www.google.co.id/search?q=lowongan+kerja">cari</a> pekerjaan <a href="http://bikinduit.com/">lain</a>. <img src='http://masputih.com/wordpress/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<h3>Struktur dasar</h3>
<p> 	Di dalam direktori projek, saya buat 4 buah sub-direktori/<em>package</em> seperti gambar di bawah ini.</p>
<div class="wp-caption aligncenter" style="width: 188px">
	<img alt="Direktori Project di FlashDevelop" src="http://old.masputih.com/images/75.jpg" title="Struktur Direktori" width="188" height="207" />
	<p class="wp-caption-text">Direktori Project di FlashDevelop</p>
</div>
<p>Berikut ini diagram dari aplikasi yang saya buat.</p>
<div class="wp-caption aligncenter" style="width: 497px">
	<img alt="Class Diagram" src="http://masputih.com/images/74.jpg" title="Class Diagram" width="497" height="515" />
	<p class="wp-caption-text">Class Diagram</p>
</div>
<h3>View &amp; ViewEvent</h3>
<p>	Package <code>view</code> berisi class yang berhubungan dengan library symbol yaitu <code>MainView</code> dan <code>ArrowButton</code>. <code>MainView</code> bertugas menyiarkan <code>ViewEvent</code> jika salah satu tombol navigasi diklik. <em>Event</em> ini ditangkap oleh <code>Controller</code> yang kemudian meng-update <code>Model</code>. Selain itu <code>MainView</code> juga menampilkan posisi kotak kuning.</p>
<p>Kenapa saya membuat <code>ViewEvent</code> dan nggak membuat <code>Controller</code> yang langsung mendengarkan <code>MouseEvent.CLICK</code> yang disiarkan oleh tombol kontrol ? Karena saya ingin meminimalkan coupling antara <code>MainView</code> dan <code>Controller</code> sehingga jika saya perlu mengubah <code>View</code>, selama event yang disiarkannya tetap bertipe <code>ViewEvent</code>, saya nggak perlu mengubah <code>Controller</code>.</p>
<p>[js]<br />
package simplemvc.view {</p>
<p>	import flash.display.MovieClip;<br />
	import flash.events.Event;<br />
	import flash.events.MouseEvent;<br />
	import flash.geom.Point;<br />
	import flash.text.TextField;<br />
	import simplemvc.events.ViewEvent;<br />
	import simplemvc.model.Model;</p>
<p>	/**<br />
	 * …<br />
	 * @author Anggie Bratadinata<br />
	 */<br />
	public class MainView extends MovieClip {</p>
<p>		//timeline objects<br />
		public var hero:MovieClip;<br />
		public var board:MovieClip;<br />
		public var leftBtn:ArrowButton;<br />
		public var rightBtn:ArrowButton;<br />
		public var upBtn:ArrowButton;<br />
		public var downBtn:ArrowButton;<br />
		public var positionTxt:TextField;</p>
<p>		private var _model:Model = Model.getInstance();</p>
<p>//———————————————————– INIT</p>
<p>		public function MainView() {</p>
<p>			initButtonListener();</p>
<p>			_model.addEventListener(Event.CHANGE, modelListener);</p>
<p>		}</p>
<p>		private function initButtonListener():void {<br />
			var i:int = 0;<br />
			while (i &lt; numChildren) {<br />
				if (this.getChildAt(i) is ArrowButton) {<br />
					this.getChildAt(i).addEventListener(MouseEvent.CLICK, buttonListener);<br />
				}<br />
				i++;<br />
			}</p>
<p>		}</p>
<p>		private function buttonListener(e:MouseEvent):void {</p>
<p>			switch(e.currentTarget) {<br />
				case leftBtn:<br />
					dispatchEvent(new ViewEvent(ViewEvent.MOVE_LEFT));<br />
				break;<br />
				case rightBtn:<br />
					dispatchEvent(new ViewEvent(ViewEvent.MOVE_RIGHT));<br />
				break;<br />
				case upBtn:<br />
					dispatchEvent(new ViewEvent(ViewEvent.MOVE_UP));<br />
				break;<br />
				case downBtn:<br />
					dispatchEvent(new ViewEvent(ViewEvent.MOVE_DOWN));<br />
				break;<br />
			}<br />
		}</p>
<p>		private function modelListener(e:Event):void {</p>
<p>			hero.x = _model.heroPos.x;<br />
			hero.y = _model.heroPos.y;</p>
<p>			positionTxt.text = _model.heroPos.toString();</p>
<p>		}</p>
<p>	}</p>
<p>}</p>
<p>[/js]</p>
<p>[js]<br />
package simplemvc.events {<br />
	import flash.events.Event;</p>
<p>	/**<br />
	 * …<br />
	 * @author Anggie Bratadinata<br />
	 */<br />
	public class ViewEvent extends Event {</p>
<p>		public static const MOVE_LEFT:String = “moveLeft”;<br />
		public static const MOVE_RIGHT:String = “moveRight”;<br />
		public static const MOVE_UP:String = “moveUp”;<br />
		public static const MOVE_DOWN:String = “moveDown”;</p>
<p>		public function ViewEvent(type:String) {<br />
			super(type, true);<br />
		} </p>
<p>		override public function clone():Event {<br />
			return new ViewEvent(type);<br />
		} </p>
<p>		override public function toString():String {<br />
			return formatToString(“ViewEvent”, “type”, “bubbles”, “cancelable”, “eventPhase”);<br />
		}</p>
<p>	}</p>
<p>}</p>
<p>[/js]</p>
<h3>Model</h3>
<p><code>Model</code> adalah bagian dimana data berada. Untuk data yang bersifat global, kita bisa mengimplementasikan <em>Singleton pattern</em>. <em>Singleton class</em> hanya bisa diinstansiasi satu kali selama aplikasi berjalan. Umumnya, referensi ke instance dari Singleton diakses dengan memanggil <em>static method</em><code> getInstance()</code>.</p>
<p>Kalo kita bekerja bersama developer lain, kita bisa mencegah mereka menginstansiasi/membuat objek Singleton dengan menggunakan <em>inner class</em> yaitu class yang didefinisikan diluar <em>package</em> tetapi masih di dalam file yang sama.</p>
<p>Model saya gunakan untuk menyimpan data berupa posisi kotak kuning. Pada saat data berubah, <code>Model</code> akan men-dispatch <code>Event.CHANGE</code> yang didengarkan oleh <code>MainView</code> yang kemudian meng-update posisi kotak kuning.</p>
<p>[js]<br />
package simplemvc.model {</p>
<p>	import flash.events.Event;<br />
	import flash.events.EventDispatcher;<br />
	import flash.geom.Point;</p>
<p>	/**<br />
	 * …<br />
	 * @author Anggie Bratadinata<br />
	 */<br />
	public class Model extends EventDispatcher {</p>
<p>		public var heroHeight:Number = 0;<br />
		public var heroWidth:Number = 0;<br />
//———————————————————– HERO VELOCITY</p>
<p>		public var vx:Number = 10;<br />
		public var vy:Number = 10;</p>
<p>//———————————————————– HERO POSITION</p>
<p>		private var _heroPos:Point = new Point();</p>
<p>		public function get heroPos():Point { return _heroPos; }</p>
<p>		public function set heroPos(value:Point):void {</p>
<p>			if (value.x &gt;= heroBounds.xMin &amp;&amp; value.x &lt;= heroBounds.xMax &amp;&amp;<br />
				value.y &gt;= heroBounds.yMin &amp;&amp; value.y &lt;= heroBounds.yMax ) {</p>
<p>				_heroPos = value;<br />
				dispatchEvent(new Event(Event.CHANGE));</p>
<p>			}<br />
		}</p>
<p>		public function moveDown():void {<br />
			heroPos = new Point(heroPos.x, heroPos.y + vy);<br />
		}</p>
<p>		public function moveUp():void {<br />
			heroPos = new Point(heroPos.x, heroPos.y — vy);<br />
		}</p>
<p>		public function moveLeft():void {<br />
			heroPos = new Point(heroPos.x — vx, heroPos.y);<br />
		}</p>
<p>		public function moveRight():void {<br />
			heroPos = new Point(heroPos.x + vx, heroPos.y );<br />
		}</p>
<p>//———————————————————– HERO BOUNDS</p>
<p>		private var _heroBounds:Object = {};</p>
<p>		public function get heroBounds():Object { return _heroBounds; }</p>
<p>		public function set heroBounds(value:Object):void {<br />
			//trace(value);<br />
			_heroBounds.xMin = value.x;<br />
			_heroBounds.xMax = value.x + value.width — heroWidth;<br />
			_heroBounds.yMin = value.y;<br />
			_heroBounds.yMax = value.y + value.height — heroHeight;</p>
<p>		}</p>
<p>//———————————————————– INIT<br />
		private static var _instance:Model;<br />
		public function Model(enf:SingletonEnforcer) {}<br />
		public static function getInstance():Model {<br />
			if (_instance == null) _instance = new Model(new SingletonEnforcer());<br />
			return _instance;<br />
		}</p>
<p>	}</p>
<p>}<br />
//INNER CLASS<br />
class SingletonEnforcer { };</p>
<p>[/js]</p>
<h3>Controller</h3>
<p><code>Controller</code> mendengarkan <code>ViewEvent</code> yang disiarkan oleh <code>MainView</code> dan meng-update <code>Model</code> berdasarkan event tersebut.</p>
<p>[js]<br />
package simplemvc.controller {<br />
	import flash.events.Event;<br />
	import flash.geom.Point;<br />
	import simplemvc.model.Model;<br />
	import simplemvc.view.*;<br />
	import simplemvc.events.*;</p>
<p>	/**<br />
	 * …<br />
	 * @author Anggie Bratadinata<br />
	 */<br />
	public class Controller {</p>
<p>		private var _model:Model = Model.getInstance();<br />
		private var _view:MainView;</p>
<p>//———————————————————– INIT</p>
<p>		public function Controller(view:MainView) {</p>
<p>			_view = view;</p>
<p>			_model.heroHeight = _view.hero.height;<br />
			_model.heroWidth = _view.hero.width;<br />
			_model.heroBounds = _view.board.getBounds(_view);</p>
<p>			_view.addEventListener(ViewEvent.MOVE_DOWN, viewListener);<br />
			_view.addEventListener(ViewEvent.MOVE_UP, viewListener);<br />
			_view.addEventListener(ViewEvent.MOVE_LEFT, viewListener);<br />
			_view.addEventListener(ViewEvent.MOVE_RIGHT, viewListener);</p>
<p>		}</p>
<p>		public function startUp():void {<br />
			_model.heroPos = new Point(0, 0);<br />
		}</p>
<p>		private function viewListener(e:ViewEvent):void {</p>
<p>			switch(e.type) {<br />
				case ViewEvent.MOVE_DOWN:<br />
					_model.moveDown();<br />
				break;<br />
				case ViewEvent.MOVE_LEFT:<br />
					_model.moveLeft();<br />
				break;<br />
				case ViewEvent.MOVE_RIGHT:<br />
					_model.moveRight();<br />
				break;<br />
				case ViewEvent.MOVE_UP:<br />
					_model.moveUp();<br />
				break;<br />
			}<br />
		}</p>
<p>	}</p>
<p>}</p>
<p>[/js]</p>
<h3>Document/Main Class</h3>
<p>[js]<br />
package  {</p>
<p>	import flash.display.MovieClip;<br />
	import simplemvc.controller.Controller;<br />
	import simplemvc.view.MainView;</p>
<p>	/**<br />
	 * …<br />
	 * @author Anggie Bratadinata<br />
	 */<br />
	public class Main extends MovieClip {</p>
<p>		public var mainView:MainView;<br />
		public var controller:Controller;</p>
<p>		public function Main() {<br />
			controller = new Controller(mainView);<br />
			controller.startUp();<br />
		}</p>
<p>	}</p>
<p>}</p>
<p>[/js]</p>
<p>Seperti Anda lihat, menulis kode dengan struktur MVC nggak terlalu sulit, hanya sedikit ngerepotin. <img src='http://masputih.com/wordpress/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<h3>Download</h3>
<a href="http://masputih.com/wordpress/wp-content/plugins/download-monitor/download.php?id=simple-mvc-src.zip" title="Downloaded 229 times" ><img src="http://masputih.com/images/disk.png" width="16" height="16"/> simple-mvc-src.zip</a> 
]]></content:encoded>
			<wfw:commentRss>http://masputih.com/2009/05/mvc-sederhana-untuk-pemula/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
