Sunday, November 1, 2009

Design Pattern in Brief (10)

Facade

Facade digunakan untuk menyembunyikan kompleksitas dan dependency terhadap subsystem. Jika tidak menggunakan facade client akan langsung berhubungan dengan subsystem sehingga terjadi tight couple seperti gambar berikut :



Namun dengan memanfaatkan facade maka antara client dan subsystem menjadi lebih loose coupling seperti gambar berikut :



Berikut adalah contoh untuk lebih memahami pattern facade : Misalkan kita memiliki tiga bean yaitu Address, Account, dan CreditCard. Kita ingin menyimpan data ketiganya tanpa client harus mengetahui ketiga bean tersebut. Di sinilah facade berperan. Berikut adalah gambar ketiga bean dan facade tersebut :





Berikut beberapa catatan penting tentang facade :
- Facade seharusnya tidak didesain untuk menyediakan fungsi tambahan
- Jangan pernah mengembalikan return value berupa komponen dalam subsystem kepada client. Sebagai contoh jangan pernah memiliki method seperti CreditCard getCreditCard() karena client akan mengetahui isi subsystem dan penggunaan facade menjadi tidak jelas.
- Penggunaan facade seharusnya untuk melakukan business service, bukan individual task.

Sunday, October 25, 2009

Not another nice story

Nyeruput teh dulu di sini, Neng. Panas banget,” ajak Kusnan (47) sambil menuju lapak warung minuman di sudut Pasar Cipulir, Jakarta Selatan, Selasa (20/10). Setumpuk celana pendek dagangannya disampirkan di sandaran kursi plastik. Tas pinggang dibukanya, hanya tampak empat lembar uang ribuan dan buku catatan kecil kumal.

Kusnan mencomot sepotong tempe goreng dan meneguk teh hangat, makan siangnya hari itu. ”Beginilah, sudah dari jam delapan keliling pasar, baru empat orang yang bayar kredit celana. Kalau lagi untung, setengah hari begini sudah dapat Rp 15.000, bisa makan nasi saya,” katanya.

Kusnan salah satu dari banyak penjual pakaian secara kredit dengan daerah operasi di pasar-pasar dan perkampungan di Jakarta. Selain celana pendek, dagangan mereka antara lain daster, pakaian anak-anak, celana jin, busana muslim, hingga pakaian dalam perempuan.

Konsumen mereka mulai dari pekerja di pasar, pemilik lapak-lapak kecil, hingga ibu-ibu rumah tangga. Harga dagangan mulai dari Rp 10.000 untuk tiga pakaian dalam anak-anak sampai Rp 200.000 untuk satu setel busana muslim plus kerudung atau jilbab. Waktu dan besar cicilan disesuaikan dengan kemampuan konsumen.

Harga celana pendek dagangan Kusnan, misalnya, rata–rata Rp 10.000-Rp 20.000. Yang berminat cukup membayar Rp 1.000 per hari. ”Setiap hari, paling tidak ada satu sampai 20 celana bisa saya jual. Cicilan pertama dibayar saat itu juga. Pemasukan lain dari nagih ke pembeli sebelumnya. Sayangnya, selalu saja ada yang menunggak, bahkan tidak bayar karena pindah atau benar-benar tidak punya uang. Mau ditarik barangnya tidak mungkin, sudah telanjur dipakai,” katanya.

Kusnan menambahkan, ia mengambil celana itu dari perajin konveksi yang juga tetangga sebelah rumah petak kontrakannya, tak jauh dari Pasar Cipulir. Bergantung model, bahan, dan ukuran, celana jualannya dipatok Rp 6.000-Rp 12.000 per potong. Kalau lancar, Kusnan sebenarnya bisa untung Rp 4.000-Rp 8.000 setiap satu celana yang lunas terbayar.

Sekitar enam tahun lalu, Kusnan mengaku memiliki lapak kecil tempat ia dan istrinya berdagang pakaian di dekat Pasar Kebayoran Lama. Namun, nasib membawanya menjadi korban gusuran. Lusinan pakaian dan lapak disita petugas, tak pernah kembali. Tanpa modal, Kusnan kesulitan memulai lagi membuka usahanya.

”Saya sudah dari umur 15 tahun merantau dari Tegal, Jawa Tengah, ke sini. Pernah jadi tukang batu sebelum akhirnya bisa buka lapak. Setelah digusur, istri dan tiga anak saya masih butuh makan. Ya sudah, jadi tukang kredit celana. Pendapatan turun, tetapi antigusuran,” katanya tergelak.

Bagi Kusnan, tidak ada alasan untuk tidak tertawa di sela-sela keletihan akibat berkeliling Pasar Cipulir dan kampung-kampung di sekitarnya. Selasa kemarin, jika nasib baik belum menghinggapinya, dipastikan hanya kurang dari Rp 4.000 yang bisa diberikannya kepada sang istri. Yang penting usaha, tegasnya.

Belum tersentuh

”Mau tidak mau, harus mau. Tidak ada yang menolong. Kucuran kredit dari pemerintah kata Neng? Tidak pernah ditawarkan ke kami. Tempat untuk pedagang kecil saja susah, apalagi bantuan modal. Mungkin karena kami enggak punya, jadi enggak pernah ditanyain maunya apa?” tambah Kusnan.

Pekerja nonformal seperti Kusnan hanyalah segelintir orang yang terselip di antara jutaan warga miskin. Di jalanan Ibu Kota, sudut-sudut perempatan, hingga kolong jembatan, tampak kehidupan orang-orang yang tidak punya jalan keluar menggantungkan hidup dari mengemis.

Berdasarkan data Badan Pusat Statistik 2009, tingkat kemiskinan sekarang mencapai 15,4 persen dari sekitar 220 juta penduduk Indonesia. Bagaimana mengentaskan mereka dari kemiskinan?

Tentu ini menjadi pekerjaan rumah bagi kepemimpinan Presiden dan Wakil Presiden baru, Susilo Bambang Yudhoyono dan Boediono. Apalagi dalam pidato kenegaraan saat dilantik di Gedung MPR/DPR, Selasa kemarin, SBY menekankan bahwa target utama kinerja pemerintahan dalam lima tahun ke depan adalah meningkatkan kesejahteraan rakyat.

Masyarakat masih menunggu bisakah target periode pemerintahan terdahulu mereduksi angka kemiskinan menjadi 8,2 persen terpenuhi dalam lima tahun ke depan? Lihat saja nanti. (NELI TRIANA)

Thomas Alva Edison

“Jenius adalah 1 persen ide cemerlang dan 99 persen kerja keras”



Thomas Alva Edison, seorang penemu terbesar di dunia, menemukan sekitar 3000 penemuan dan 1.093 diantaranya telah dipatenkan. Edison dilahirkan pada tanggal 11 Februari 1847 di Milan, Ohio, Amerika Serikat dari pasangan suami-Istri Samuel Ogden seorang tukang kayu dan Nancy Elliot seorang guru. Keduanya merupakan keturunan Belanda. Pada usia 7 tahun, edison kecil pindah ke kota Port Huron, Michigan dan bersekolah di Port Huron. Namun tidak lama, 3 bulan kemudian ia dikeluarkan dari Sekolah karena menurut gurunya “Dia terlalu bodoh” sehingga tidak mampu menerima pelajaran apa pun, dia pun sering dipanggil idiot oleh gurunya.

Sang ibu, Nancy Elliot memutuskan untuk berhenti sebagai guru dan kemudian berkonsentrasi mengajari Edison baca tulis dan hitung menghitung.

“My mother was the making of me. She was so true, so sure of me; and I felt I had something to live for, someone I must not disappoint.”

Begitulah perkataan Edison kecil yang menunjukkan motivasi dalam diri Edison yang cukup kuat dalam belajar. Setelah dia bisa membaca, Edison jadi gemar membaca, ia membaca apa saja yang dapat dijumpainya ia membaca ensiklopedia, Sejarah Inggris, Kamus IPA karangan Ure, Principia karangan Newton dan juga Ilmu Kimia karangan Richard G. Parker. kegemarannya yang menonjol adalah membaca, berpikir dan berkeksperimen.

Pada umur 12 Tahun Edison menjadi penjual koran, permen, kacang dan kue di kereta api, sama seperti penjual asongan yang sering kita temui di kereta api ekonomi di Indonesia. Keuntungan dari berdagang itu sebagiannya dia berikan kepada orang tuanya dan sebagiannya dia simpan sebagai modal. Di dalam kereta api, ia menerbitkan koran Weekly Herald sembari mengadakan eksperimen di salah satu gerbong kereta api, setelah sebelumnya meinta ijin perusahaan kereta api “Grand Trunk Railway”.

Pada suatu malam Edison tidak sengaja menumpahkan sebuah cairan kimia sehingga menyebabkan sebuah gerbong hampir terbakar. Karena kasus ini Edison ditampar kondektur hingga pendengarannya rusak, kemudian dia dilarang bekerja di kereta api. Namun Edison tidak menganggap pendengarannya yang rusak sebagai cacat, namun justru dia menganggapnya secara positif sebagai sebuah keuntungan sehingga ia memiliki lebih banyak waktu untuk berfikir daripada mendengarkan omongan – omongan kosong.

Pada usia 15 tahun Edison remaja menyelamatkan nyawa anak kepala stasiun yang hampir tergilas gerbong kereta api. Karena merasa berhutang jasa, sang kepala stasiun tersebut akhirnya mengajarkan cara pengiriman telegram, Edison hanya memerlukan waktu 3 bulan untuk menguasai pelajaran gratis tersebut. Sesudah itu, ia mendapat pekerjaan sebagai operator telegraf.

Penemuan pertama yang dia patenkan adalah electric vote recorder, namun karena tidak laku, Edison akhirnya beralih ke penemuan yang lebih komersial. Edison kemudian menemukan stock ticker atau mesin telegraf. Peralatan itu dijualnya dan laku 40.000 dollar Amerika serikat (Sekitar 390 juta rupiah). Edison hampir – hampir pingsan melihat uang sebanyak itu. Uang ini dipakai Edison untuk mendirikan pabrik di Newark dan merekrut 300 orang pekerja sekaligus, disini ia mengembangkan telegraf sehingga mampu mengirimkan 4 berita sekaligus.

Pada umur 29 tahun, Edison mendirikan laboratorium riset untuk industri di Menlo Park, New Jersey. dan dalam 13 bulan ia menemukan 400 macam penemuan yang kemudian mengubah pola hidup sebagian besar orang-orang di dunia.

Tahun 1877 ia berkonsentrasi pada lampu pijar. Edison sadar bahwa betapa pentingnya sumber cahaya ini bagi manusia. Dia menghabiskan 40.000 dollar dalam kurun waktu dua tahun untuk eksperimen lampu pijar. Yang menjadi masalah adalah menemukan bahan yg bisa berpijar ketika dialiri arus listrik namun tidak terbakar. Total ada sekitar 6000 bahan yang dicobanya. Melalui usaha keras Edison, akhirnya pada tanggal 21 Oktober 1879 lahirlah lampu pijar listrik pertama yang mampu menyala selama 40 jam. Tahun 1882, untuk pertama kalinya dalam sejarah lampu-lampu listrik di pasang di jalan-jalan dan di rumah rumah

Sungguh patut direnungkan ketika saat keberhasilan dicapainya, dia sempat ditanya: Apa kunci kesuksesannya. Thomas Alfa Edison menjawab:

“Saya sukses, karena saya telah kehabisan apa yang disebut dengan kegagalan”

Ketika dia telah banyak sekali mengalami kegagalan yang berulang-ulang. Bahkan saat dia ditanya apakah dia tidak bosan dengan kegagalannya, Thomas Alfa Edison menjawab:

“Dengan Kegagalan Tersebut, Saya malah mengetahui ribuan cara agar lampu tidak menyala”

This is Amazing!!, Edison memandang sebuah kegagalan sebagai sebuah hal yang sangat positif. Kegagalan bukan kekalahan tapi sebagai sebuah keuntungan. Cara memandang yang positif ini membuat Edison mampu meyakinkan orang lain untuk tetap mendanai proyeknya meskipun gagal berulang – ulang kali. Mungkin prinsip Edison inilah yang patut kita terapkan dalam kehidupan kita sehari. Bahwa sebenarnya kita tidak pernah mengalami kerugian, dan sesungguhnya kerugian itu bermula dari sikap dan cara pandang kita sendiri yang negatif.

Edison telah banyak menghasilkan berbagai penemuan yang sangat berharga bagi perkembangan umat manusia. Telegraf cetak, pulpen elektrik, proses penambangan magnetik, torpedo listrik, karet sintetis, baterai alkaline, pengaduk semen, mikrofon, transmiter telepon karbon dan proyektor gambar bergerak adalah beberapa dari penemuan Edison.

Melewati tahun 1920-an kondisi kesehatannya kian memburuk dan Edison meninggal dunia tanggal 18 Oktober 1931 pada usia 84 tahun.

Sunday, October 18, 2009

Design Pattern in Brief (9)

Chain of Responsibility

Pattern ini mirip dengan model layering dalam arsitektur software. Pattern ini menjelaskan bahwa antara object pengirim request dan object-object yang menangani request sebaiknya terpisah bahkan benar-benar tidak saling terkait (loosely coupling).

Jika ada lebih dari satu object yang bertugas menangani request, maka prosesnya dilakukan secara berurutan. Urutan tersebut membentuk sebuah rantai di mana setiap object mempunyai pointer yang merujuk ke chain selanjutnya.

Object pertama yang menerima request bisa memutuskan apakah akan menghandle request atau meneruskannya ke object selanjutnya. Request tersebut berjalan terus sampai dihandle oleh salah satu object atau request sampai di ujung rantai tanpa ada yang menghandlenya. Dengan kata lain, setelah melewati serangkaian rantai tersebut, request bisa saja tidak ada yang menghandlenya.

Berikut adalah karakteristik dari Chain of Responsibility :

- Sekumpulan request handler, dan urut-urutannya sehingga membentuk sebuah rantai dapat dilakukan secara dinamis saat runtime oleh klien.
- Klien bisa memiliki rantai request handler yang berbeda-beda tergantung jenis requestnya.
- Baik klien maupun masing-masing object request handler tidak perlu tahu object handler mana yang akhirnya menghandle request.
- Setelah melalui rantai request handler, request bisa saja tidak ada yang menghandlenya.

Untuk aplikasinya perhatikan contoh berikut :

Misal kita mempunyai sebuah purchase request.



Agar purchase request ini bisa dikirim maka harus melewati serangkaian pemeriksaan batas pembelian oleh 4 manajerial level.





Perhatikan diagram dan kode berikut :



Kita memiliki PRHandler sebagai parent dari keempat manajerial class request handler di atas. Berikut adalah codenya

package edu.mat.pattern.chain;

import edu.mat.pattern.request.PurchaseRequest;

public abstract class RequestHandler {

protected RequestHandler nextHandler;

public abstract boolean authorize(PurchaseRequest request);

public RequestHandler getNextHandler() {
return nextHandler;
}

public void setNextHandler(RequestHandler nextHandler) {
this.nextHandler = nextHandler;
}
}

package edu.mat.pattern.chain;

import edu.mat.pattern.request.PurchaseRequest;

public class BranchManager extends RequestHandler {

private static final int LIMIT = 25000;

@Override
public boolean authorize(PurchaseRequest request) {
// do authorization
if(request.getAmount() <= LIMIT) {
System.out.println("Authorized by branch manager...");
return true;
} else
return nextHandler.authorize(request);
}

}

package edu.mat.pattern.chain;

import edu.mat.pattern.request.PurchaseRequest;

public class PresidentCOO extends RequestHandler {

private static final int LIMIT = 400000;

@Override
public boolean authorize(PurchaseRequest request) {
// do authorization
if(request.getAmount() <= LIMIT) {
System.out.println("Authorized by president coo...");
return true;
} else
return nextHandler.authorize(request);
}

}

package edu.mat.pattern.chain;

import edu.mat.pattern.request.PurchaseRequest;

public class RegionalDirector extends RequestHandler {

private static final int LIMIT = 100000;

@Override
public boolean authorize(PurchaseRequest request) {
// do authorization
if(request.getAmount() <= LIMIT) {
System.out.println("Authorized by regional director...");
return true;
} else
return nextHandler.authorize(request);
}

}

package edu.mat.pattern.chain;

import edu.mat.pattern.request.PurchaseRequest;

public class VicePresident extends RequestHandler {

private static final int LIMIT = 200000;

@Override
public boolean authorize(PurchaseRequest request) {
// do authorization
if(request.getAmount() <= LIMIT) {
System.out.println("Authorized by vice president...");
return true;
}else
return nextHandler.authorize(request);
}

}

package edu.mat.pattern.request;

public class PurchaseRequest {

private String id;
private String description;
private double amount;

public PurchaseRequest(String id, String description, double amount) {
super();
this.id = id;
this.description = description;
this.amount = amount;
}

public String getId() {
return id;
}

public String getDescription() {
return description;
}

public double getAmount() {
return amount;
}

}

package edu.mat.pattern.main;

import edu.mat.pattern.chain.BranchManager;
import edu.mat.pattern.chain.PresidentCOO;
import edu.mat.pattern.chain.RegionalDirector;
import edu.mat.pattern.chain.VicePresident;
import edu.mat.pattern.request.PurchaseRequest;

public class Main {

public static void main(String args[]) {
BranchManager branchManager = new BranchManager();
PresidentCOO presidentCOO = new PresidentCOO();
RegionalDirector regionalDirector = new RegionalDirector();
VicePresident vicePresident = new VicePresident();

branchManager.setNextHandler(regionalDirector);
regionalDirector.setNextHandler(vicePresident);
vicePresident.setNextHandler(presidentCOO);
presidentCOO.setNextHandler(null);

PurchaseRequest request = new PurchaseRequest("one", "request one", 300000);
branchManager.authorize(request);
}
}

Jika dijalankan :

Authorized by president coo...

Saturday, October 17, 2009

Design Pattern in Brief (8)

Adapter

Adapter adalah salah satu pattern yang populer. Untuk memahami pattern ini perhatikan contoh berikut :

Kita ingin melakukan validasi terhadap alamat customer. Untuk keperluan ini kita telah memiliki sebuah bean Customer, sebuah interface untuk validasi IAddressValidator, dan sebuah class konkret yang implement interface tersebut USAddressValidator.



Karena customer tidak hanya dari US saja, kita ingin menambah validator untuk Kanada, misalnya. Misal untuk alamat Kanada kita telah mempunyai sebuah class lain, CAAddress, yang tidak sama interfacenya dengan USAddressValidator. Interface dalam hal ini bukan berarti java interface atau GUI, tapi yang dimaksud adalah bahwa jika kita menerapkan CAAddress dalam struktur desain kita, maka akan terlihat aneh menurut klien. Karena itu kita membuat sebuh class lagi CAAddressAdapter yang berisi reference ke CAAddress.




Struktur class di atas bisa dilihat dalam diagram berikut :

Wednesday, October 14, 2009

Design Pattern in Brief (7)

Decorator

Dalam pemrograman OOP kita pasti sudah terbiasa dengan pattern inheritance. Inheritance adalah salah satu dasar dari OOP. Decorator bisa dibilang kebalikan dari inheritance. Untuk lebih memahami pattern ini perhatikan contoh berikut :

Misal kita mempunyai struktur class untuk logger seperti gambar berikut :



Dan selanjutnya sesuai dengan bisnis proses yang ada, kita diharuskan untuk bisa menampilkan dan menyimpan log berupa struktur HTML dan text terenkripsi. Bagaimana kita melakukan ini? Pendekatan pertama kita adalah dengan melakukan inheritance terhadap ConsoleLogger dan FileLogger. Dengan demikian kita akan mendapatkan struktur class seperti gambar berikut :



Dengan diagram di atas kita akan mendapatkan struktur file yang kompleks. Kita akan mencoba mengatasinya dengan pattern Decorator. Decorator menyarankan agar kita menggunakan wrapper, bukan inheritance. Pada contoh di atas, Decorator yang akan kita buat harus juga implements interface yang sama dengan object yang akan kita buat wrappernya, dalam hal ini interface Logger. Saat klien berinteraksi dengan decorator, mereka berinteraksi dengan cara yang sama seperti berinteraksi dengan object yang dibut wrappernya. Berikut adalah diagram untuk decorator :



Terlihat dari diagram di atas bahwa HTMLLogger dan EncryptLogger override method log(String) dari class di atasnya. Di dalam masing2 method tersebut HTMLLogger membuat inputan yang di-log berbentuk html dan EncryptLogger mengenkripsi inputannya. Bagaimana selanjutnya cara menampilkan ke console atau ke file? Perhatikan bahwa LoggerDecorator mempunyai sebuah variabel logger bertipe Logger. Variabel ini bisa diisi dengan wrapper class yang sesuai, misal ConsoleLogger atau FileLogger.

Berikut adalah diagram akhir yang menggambarkan struktur class :


Sunday, October 11, 2009

Design Pattern in Brief (6)

Visitor

Untuk memahami visitor perhatikan contoh berikut : Misal kita memiliki list of order yang bisa kita kategorikan menjadi tiga yaitu California order, Non California order, dan Overseas order. Saat mengiterasi list tersebut, untuk masing-masing order kita ingin menjalankan sebuah method, misalkan accept(), namun method accept ini akan melakukan hal-hal yang berbeda tergantung jenis ordernya. Bagaimana kita melakukan hal ini? Inilah yang coba dipecahkan pattern visitor.

Untuk mengimplementasikannya kita akan membuat sebuah interface IOrder yang berisi sebuah method yang sama, accept(IVisitor visitor) yang akan dieksekusi lewat list. Selanjutnya kita membuat tiga class, masing-masing untuk order yang berbeda.

Untuk visitornya, kita membuat sebuah interface, IVisitor, yang memiliki tiga method visit() dengan parameter yang berbeda, masing-masing untuk tiap order. Kemudian kita akan mengimplementasikan IVisitor dalam sebuah class VisitorImpl yang akan mengimplementasikan masing-masing method visit() tersebut.

Kita bisa merangkum class-class yang terlibat dalam diagram berikut :







Dan berikut adalah codenya :

package edu.mat.pattern;

public interface IOrder {

public void accept(IVisitor visitor);
}

package edu.mat.pattern;

public class OrderCalifornia implements IOrder {

private String message;

@Override
public void accept(IVisitor visitor) {
visitor.visit(this);
}

public String getMessage() {
if(message == null)
message = "Order California";
return message;
}

public void setMessage(String message) {
this.message = message;
}

}

package edu.mat.pattern;

public class OrderNonCalifornia implements IOrder {

private String state;

@Override
public void accept(IVisitor visitor) {
visitor.visit(this);
}

public String getState() {
if(state == null)
state = "New York";
return state;
}

public void setState(String state) {
this.state = state;
}

}

package edu.mat.pattern;

public class OrderOverseas implements IOrder {

private String destinationCountry;

@Override
public void accept(IVisitor visitor) {
visitor.visit(this);
}

public String getDestinationCountry() {
if(destinationCountry == null)
destinationCountry = "Indonesia";
return destinationCountry;
}

public void setDestinationCountry(String destinationCountry) {
this.destinationCountry = destinationCountry;
}

}

package edu.mat.pattern;

public interface IVisitor {

public void visit(OrderCalifornia orderCalifornia);
public void visit(OrderNonCalifornia orderNonCalifornia);
public void visit(OrderOverseas orderOverseas);
}

package edu.mat.pattern;

public class VisitorImpl implements IVisitor {

@Override
public void visit(OrderCalifornia orderCalifornia) {
System.out.println(orderCalifornia.getMessage());
}

@Override
public void visit(OrderNonCalifornia orderNonCalifornia) {
System.out.println(orderNonCalifornia.getState());
}

@Override
public void visit(OrderOverseas orderOverseas) {
System.out.println(orderOverseas.getDestinationCountry());
}

}

package edu.mat.pattern;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class Main {

public static void main(String[] args) {
IVisitor visitor = new VisitorImpl();
List orders = new ArrayList();
orders.add(new OrderCalifornia());
orders.add(new OrderNonCalifornia());
orders.add(new OrderOverseas());

Iterator iter = orders.iterator();
while(iter.hasNext()) {
iter.next().accept(visitor);
}
}
}

Monday, October 5, 2009

Design Pattern in Brief (5)

Flyweight

Setiap object mengandung informasi yang tersimpan dalam propertynya. Informasi tersebut bisa dibagi menjadi dua kategori yaitu informasi intrinsik dan ekstrinsik. Informasi intrinsik adalah informasi yang independen, yaitu informasi yang bersifat tetap atau konstan terhadap instance suatu class. Contohnya adalah informasi nama dan alamat perusahaan pada class kartu identitas pegawai. Informasi ekstrinsik adalah informasi yang bersifat berubah-ubah tergantung object tempat informasi tersebut berada. Hal ini berarti informasi tersebut "unique" untuk tiap instance dari class. Sebagai contoh, nama dan jabatan pegawai adalah "unique" untuk tiap pegawai.

Sekarang misalkan kita memiliki sebuah class employee yang bisa dibuat menjadi ribuan object dan di dalam class tersebut tersimpan informasi intrinsik dan ekstrinsik. Jika hal itu terjadi maka akan menimbulkan overhead pada memori karena menyimpan tiap informasi intrinsik yang sebetulnya sama bagi semua object employee tersebut. Untuk mengatasi hal inilah pattern flyweight dibuat.

Pattern flyweight menyarankan untuk memisah informasi intrinsik ke dalam object sendiri yang disebut object flyweight. Tiap object yang membutuhkan object flyweight dapat berbagi instance flyweight sehingga akan mampu menghemat memori dan waktu yang dibutuhkan untuk membuat object (object creation time).

Berikut adalah requirement yang harus dipenuhi untuk membuat flyweight :
- Hanya ada satu object flyweight dan object tersebut digunakan bersama oleh object lain yang membutuhkan.
- Object yang memanfaatkan flyweight di atas tidak boleh secara langsung membuat object flyweight.

Untuk memenuhi requirement di atas maka berikut adalah pendekatan yang dilakukan
- Class flyweight harus memiliki konstruktor private sehingga tidak bisa dibuat oleh class lain.
- Pattern singleton digunakan untuk memastikan bahwa tidak ada duplikasi object.

package edu.mat.pattern;

public interface IFlyweight {

public String getCompanyName();
public String getCompanyAddress();

}

package edu.mat.pattern;

import java.util.HashMap;
import java.util.Map;

public class FlyweightFactory {

private static final FlyweightFactory INSTANCE = new FlyweightFactory();
private Map flyweightList;

private FlyweightFactory() {
super();
this.flyweightList = new HashMap();
}

public static FlyweightFactory getInstance() {
return INSTANCE;
}

public synchronized Flyweight getFlyweight(String companyName) {
if(flyweightList.get(companyName) == null) {
Flyweight fly = new Flyweight(companyName);
flyweightList.put(companyName, fly);
return fly;
}
else
return flyweightList.get(companyName);
}

private class Flyweight implements IFlyweight {

private String companyName;
private String companyAddress;

private Flyweight(String companyName) {
super();
this.companyName = companyName;
if(companyName != null) {
if(companyName.equals("IBM"))
this.companyAddress = "California";
else if(companyName.equals("SUN"))
this.companyAddress = "Silicon Valley";
}
}

@Override
public String getCompanyAddress() {
return companyAddress;
}

@Override
public String getCompanyName() {
return companyName;
}

}

}

package edu.mat.pattern;

public class Main {

public static void main(String[] args) {
FlyweightFactory factory = FlyweightFactory.getInstance();
System.out.println(factory.getFlyweight("SUN"));
System.out.println(factory.getFlyweight("IBM"));
System.out.println(factory.getFlyweight("SUN"));
System.out.println(factory.getFlyweight("IBM"));
}
}

Saat dijalankan akan menghasilkan :

edu.mat.pattern.FlyweightFactory$Flyweight@42e816
edu.mat.pattern.FlyweightFactory$Flyweight@9304b1
edu.mat.pattern.FlyweightFactory$Flyweight@42e816
edu.mat.pattern.FlyweightFactory$Flyweight@9304b1

Perhatikan bahwa tepat hanya ada satu object flyweight untuk tiap companyName yang sama.

Sunday, October 4, 2009

Design Pattern in Brief (4)

Iterator

Iterator digunakan untuk mengakses isi sebuah container secara urut tanpa harus mengetahui isi container tersebut. Container yang dimaksud adalah collection of data. Di java, Iterator dapat diterapkan dengan implement java.util.Iterator. Ada dua macam iterator yaitu internal dan eksternal.

Misalkan kita memiliki sebuah container, maka internal iterator adalah iterator yang dimaintain oleh container tersebut. Container bertanggung jawab terhadap state dari iterator dan hanya bisa ada satu iterator dalam satu container. Sedangkan eksternal iterator adalah iterator yang diletakkan dalam object terpisah dari container. Jadi sekarang ada dua object, container dan iterator, di mana container mengembalikan sebuah object bertipe iterator dalam sebuah methodnya, misalnya getIterator().

Berikut adalah contoh internal iterator :
package edu.mat.pattern.iterator;

import java.util.Enumeration;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.Vector;

/**
* Internal Iterator means the collection itself needs to maintain the iterator,
* that's why this collection extends Iterator. So this class can be viewed as both
* a container and an iterator.
* */
public class InternalIterator implements Iterator {

private Vector data;
private Enumeration enumeration;
private Employee nextEmployee;

public InternalIterator() {
data = new Vector();
data.add(new Employee("Santoso", "Los Angeles"));
data.add(new Employee("Rochmat", "New York"));

enumeration = data.elements();
}

@Override
public boolean hasNext() {
nextEmployee = null;
while(enumeration.hasMoreElements()) {
Employee employee = enumeration.nextElement();
nextEmployee = employee;
if(employee != null)
return true;
}
return false;
}

@Override
public Employee next() {
if(nextEmployee == null)
throw new NoSuchElementException();
else
return nextEmployee;
}

@Override
public void remove() {
// do nothing because we don't wanna remove anything

}

}

Dan berikut adalah contoh eksternal iterator yang terdiri dari container dan iterator :
package edu.mat.pattern.iterator;

import java.util.Enumeration;
import java.util.Iterator;
import java.util.Vector;

public class ExternalContainer {

private Vector data;

public ExternalContainer() {
data = new Vector();
data.add(new Employee("Santoso", "Los Angeles"));
data.add(new Employee("Rochmat", "New York"));
}

public Enumeration getAllEmployees() {
return data.elements();
}

public Iterator getEmployeeByName(String name) {
return new ExternalIterator(this, name);
}

}

package edu.mat.pattern.iterator;

import java.util.Enumeration;
import java.util.Iterator;
import java.util.NoSuchElementException;

public class ExternalIterator implements Iterator {

private String name;
private Enumeration enumeration;
private Employee nextEmployee;

public ExternalIterator(ExternalContainer employees, String name) {
this.name = name;
this.enumeration = employees.getAllEmployees();
}

@Override
public boolean hasNext() {
nextEmployee = null;
while(enumeration.hasMoreElements()) {
Employee employee = enumeration.nextElement();
nextEmployee = employee;
if(employee != null) {
if(name == null)
return true; // jika tidak ada filter maka return true
else {
if(employee.getName() != null) {
if(name.equals(employee.getName()))
return true; // jika ada filter dan curr employee name sama maka return true
// jika ada filter tapi curr employee name tdk sama maka continue
} // jika ada filter tapi curr employee name null maka continue
}
}
}
return false; // jika next employee = null maka return false
}

@Override
public Employee next() {
if(nextEmployee == null)
throw new NoSuchElementException();
else
return nextEmployee;
}

@Override
public void remove() {
// do nothing because we don't wanna remove anything

}

}

Thursday, September 17, 2009

Design Pattern in Brief (3)

Composite

Setiap komponen atau objek bisa dikelompokkan ke dalam salah satu dari dua kategori, individual komponen atau komposit komponen (yang terdiri dari individual komponen dan komposit komponen lain). Composite pattern digunakan untuk memodelkan sebuah interface sehingga kedua komponen tersebut bisa dilihat sebagai sebuah komponen yang sama dari sisi klien. Sederhananya, klien akan melihat dan bisa memperlakukan kedua komponen tersebut dengan cara yang sama.

Implementasi composite bisa dilihat pada tree, yang terdiri dari parent nodes dan leaves. Berikut ini kita mempunyai sebuah interface FileSystemComponent yang mempunyai method-method untuk megakses file komponen dan direktori komponen.



Method addComponent() pada class DirComponent digunakan untuk menambah file atau direktori baru di susunan file sistem tersebut. Sedangkan untuk mendapatkan ukuran dari file sistem yang ada, klien cukup memanggil getComponentSize(). Klien memperlakukan sama kedua file sistem tersebut, file dan direktori, untuk mendapatkan ukuran file sistem yang ada.

Design berikut adalah perbaikan dari design sebelumnya.



Kita bisa memanfaatkan interface atau abstract class dengan memindahkan semua method di DirComponent ke interface atau abstract tersebut. Karena class FileComponent tidak seharusnya memiliki method selain getComponentSize() maka FileComponent bisa throw exception jika method2 tersebut dipanggil dari dirinya. Sedangkan DirComponent harus mengoverride method2 tersebut.

public abstract class FileSystemComponent {
String name;
public FileSystemComponent(String cName) {
name = cName;
}
public void addComponent(FileSystemComponent component)
throws CompositeException {
throw new CompositeException(
"Invalid Operation. Not Supported");
}
public FileSystemComponent getComponent(int componentNum)
throws CompositeException {
throw new CompositeException(
"Invalid Operation. Not Supported");
}
public abstract long getComponentSize();
}

public class FileComponent extends FileSystemComponent {
private long size;
public FileComponent(String cName, long sz) {
super(cName);
size = sz;
}
public long getComponentSize() {
return size;
}
}

public class DirComponent extends FileSystemComponent {
Vector dirContents = new Vector();
//individual files/sub folders collection
public DirComponent(String cName) {
super(cName);
}
public void addComponent(FileSystemComponent fc)
throws CompositeException {
dirContents.add(fc);
}
public FileSystemComponent getComponent(int location)
throws CompositeException {
return (FileSystemComponent) dirContents.elementAt(
location);
}
public long getComponentSize() {
long sizeOfAllFiles = 0;
Enumeration e = dirContents.elements();
while (e.hasMoreElements()) {
FileSystemComponent component =
(FileSystemComponent) e.nextElement();
sizeOfAllFiles = sizeOfAllFiles +
(component.getComponentSize());
}
return sizeOfAllFiles;
}
}

Yang perlu diperhatikan adalah bahwa setiap kali kita menambah method baru, misal removeComponent() untuk DirComponent, maka kita juga harus menambahkannya di abstract atau interfacenya (dan FileComponent harus mengoverridenya). Kenapa? Karena kedua class child, FileComponent dan DirComponent, harus bisa dilihat dan diperlakukan sama oleh klien.

Saturday, September 12, 2009

Debugging in GWT

Days a go I tried to debug my GWT code and... nothing happened. In GWT, we can debug our code in hosted mode but not in web mode by the way. My breakpoint didn't hit by debugger. How could it be? After googling for awhile I found out that I'm not the only one who has the same problem. Some people say that they have problem when it is jdk 1.6.0_14, and when they downgrade to 1.6.0_13, it runs well without any debugging problems.

But before I revert back to older version, it's a good practice to upgrade first. So I decided to upgrade to 1.6.0.16 (currently available version). And when I run eclipse debugger, it works. Fiuh...

Design Pattern in Brief (2)

Prototype

Prototype bisa dipandang sebagai salah satu alternatif dari Factory dan Abstract Factory. Untuk memahaminya bisa dilihat pada contoh-contoh berikut.



Design di atas bisa diimplementasikan dengan abstract factory seperti berikut :



Dengan prototype kita bisa mengimplementasikannya seperti :





public class HostingPlanKit {
private HostingPlan basicPlan;
private HostingPlan premiumPlan;
private HostingPlan premPlusPlan;
public HostingPlanKit(HostingPlan basic, HostingPlan premium,
HostingPlan premPlus) {
basicPlan = basic;
premiumPlan = premium;
premPlusPlan = premPlus;
}
public HostingPlan getBasicPlan() {
return (HostingPlan) basicPlan.clone();
}
public HostingPlan getPremiumPlan() {
return (HostingPlan) premiumPlan.clone();
}
public HostingPlan getPremPlusPlan() {
return (HostingPlan) premPlusPlan.clone();
}


public class HostingPlanManager {
public static HostingPlanKit getHostingPlanKit(
String platform) {
HostingPlan basicPlan = null;
HostingPlan premiumPlan = null;
HostingPlan premPlusPlan = null;
if (platform.equalsIgnoreCase("Win")) {
basicPlan = new WinBasic();
premiumPlan = new WinPremium();
premPlusPlan = new WinPremPlus();
}
if (platform.equalsIgnoreCase("Unix")) {
basicPlan = new UnixBasic();
premiumPlan = new UnixPremium();
premPlusPlan = new UnixPremPlus();
}
return new HostingPlanKit(basicPlan, premiumPlan,
premPlusPlan);
}
}

Thursday, September 10, 2009

Shallow Copy & Deep Copy

Semua java class memilik method clone() yang diturunkan dari java.lang.Object. Method tersebut membuat copy dari sebuah object sebagai shallow copy. Apa yang dimaksud dengan shallow copy adalah :
1. Java membuat object baru di memori, termasuk membuat instance variabel yang bertipe primitive sekalipun.
2. Object lain yang direference oleh class yang diclone tersebut tidak dibuat copynya, hanya membuat reference baru ke object tersebut. Jadi kini ada dua reference yang mengarah pada object yang sama.

public class Car extends Object implements Cloneable {

private String carName;
private String carType;
private SUV suv;

public String getCarName() {
return carName;
}

public void setCarName(String carName) {
this.carName = carName;
}

public String getCarType() {
return carType;
}

public void setCarType(String carType) {
this.carType = carType;
}

public SUV getSuv() {
return suv;
}

public void setSuv(SUV suv) {
this.suv = suv;
}

@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}

@Override
public String toString() {
return "carName : " + carName + " car type : " + carType + " suv : " + suv;
}

}

public class SUV {

private String suvType;
private String suvModel;

public String getSuvType() {
return suvType;
}

public void setSuvType(String suvType) {
this.suvType = suvType;
}

public String getSuvModel() {
return suvModel;
}

public void setSuvModel(String suvModel) {
this.suvModel = suvModel;
}

@Override
public String toString() {
return "suv type : " + suvType + " suv model : " + suvModel;
}

}

public class Main {

public static void main(String[] args) {
SUV suv = new SUV();
suv.setSuvModel("suv model 1");
suv.setSuvType("suv type 1");

Car car = new Car();
car.setCarName("Timor");
car.setCarType("Sedan");
car.setSuv(suv);

System.out.println("car 1 : " + car);
try {
Car car2 = (Car) car.clone();
suv.setSuvModel("suv model update");
System.out.println("car 2 : " + car2);
System.out.println("car 1 : " + car);
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
}
car 1 : carName : Timor car type : Sedan suv : suv type : suv type 1 suv model : suv model 1
car 2 : carName : Timor car type : Sedan suv : suv type : suv type 1 suv model : suv model update
car 1 : carName : Timor car type : Sedan suv : suv type : suv type 1 suv model : suv model update

Sedangkan deep copy adalah :
1. Java menduplikasi object yang dicopy termasuk variabel yang primitif.
2. Object yang direference pun dicopy sehingga kini dua object yang diclone merefer ke dua object yang berbeda.

Bagaimana implementasi deep copy pada java? Kita bisa mengoverride method clone() untuk keperluan deep copy ini.

Monday, September 7, 2009

Design Pattern in Brief

Immutable

Immutable berarti tidak dapat diubah. Apanya yang tidak dapat diubah? Tentunya state dari suatu object, secara teknis, tentu nilai dari variabelnya. Dalam design pattern kita bisa membuat sebuah object menjadi immutable dengan cara
1. Semua instance variabel harus diset hanya dari konstruktor. Tidak ada method atau cara lain untuk mengeset nilai variabel selain dari konstruktor tsb. Dengan kata lain jadikan instance variabel private dan tanpa setter.
2. Agar class yang kita inginkan menjadi immutable tidak bisa di-extends, maka kita deklarasikan class tersebut sebagai final. Dengan demikian tidak ada cara untuk mengoverride method yang kita miliki.
3. Semua instance variabel harus dideklarasikan final sehingga hanya bisa diinisialisasi sekali, lewat konstruktor.
4. Jika sebuah method mempunyai return value berupa class dari object tersebut, maka sebaiknya ia tidak mengembalikan object yang sebenarnya melainkan copy atau clonenya.

Monitor

Menulis tentang monitor tentunya mengingatkan pada kuliah Sistem Operasi oleh Bapak Mochammad Husni :). Tak salah lagi, topik yang jadi hot thread pada kuliah itu adalah race condition, deadlock. Monitor adalah mekanisme yang digunakan untuk mengatasi deadlock sehingga hanya satu thread yang bisa mengakses sebuah method dalam satu waktu. Pada Java hal ini diatasi dengan mendeklarasikan sebuah method sebagai synchronized.

Factory



Factory dapat digambarkan sebagai sebuah class yang mengotomatisasi pembuatan sebuah object. Dalam diagram berikut kita memiliki sebuah parent class (bisa abstract, interface, atau konkret class) yang diextend oleh dua subclass. Sebuah class lain, yang bisa jadi bukan bagian dari aplikasi kita, ingin memanfaatkan class yang telah kita buat tersebut. Yang class lain tersebut ketahui hanyalah parent class saja. Mereka tidak tahu menahu struktur hirarki class kita. Sementara itu struktur yang kita buat adalah request harus didelegasikan ke masing-masing subclass yang bersesuaian. Bagaimana kita dapat menginstansiasi class-class yang berbeda dan mengembalikan return value dengan tipe yang sama adalah tugas Class Factory.

Pada gambar kita memiliki dua buah struktur factory. Pertama adalah sebuah interface sebagai contract dengan class lain. Kedua adalah Konkret class yang berisi factory method yang bertugas 'memilih' subclass mana yang harus diinstansiasi. Bagaimana cara factory method melakukan tugasnya? Sederhananya dengan if-then rules atau switch.

Singleton

Dalam design pattern, singleton berarti hanya ada satu instance. Bagaimana cara mendapatkan hanya satu instance selama aplikasi berjalan? Kita bisa melakukannya dengan meletakkan variabel dengan tipe class singleton sebagai global variabel, semua class yang membutuhkan object tersebut merefer ke variabel global yang dimaksud. Namun walaupun demikian, client masih tetap bisa membuat instance dari class tersebut bukan? Walaupun bukan sebagai global variabel.

Sebuah class yang bisa membuat dirinya sendiri hanya mempunyai satu instance disebut singleton class. Berikut adalah cara membuat class menjadi singleton
1. Buat constructornya private. Dengan demikian tidak ada cara class lain menginstansiasi class tersebut selain dirinya sendiri.
2. Di dalam class singleton tersebut buat public static method dengan nama getInstance().
3. Di dalam body method getInstance() buat instance yang hanya dibuat sekali pada saat pertama class di-invoke.

public class Singleton {
private static final Singleton INSTANCE = new Singleton();

// Private constructor prevents instantiation from other classes
private Singleton() {}

public static Singleton getInstance() {
return INSTANCE;
}
}

Pada code di atas, instance singleton dibuat hanya sekali yaitu saat class dipanggil. Namun cara ini memiliki kelemahan yaitu instance dibuat saat pertama class diinisialisasi, bukan saat dipanggil.

public class Singleton {
// Private constructor prevents instantiation from other classes
private Singleton() {}

/**
* SingletonHolder is loaded on the first execution of Singleton.getInstance()
* or the first access to SingletonHolder.INSTANCE, not before.
*/
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}

public static Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}


Code di atas adalah yang diusulkan oleh Bill Pugh. Instance benar-benar dibuat saat getInstance() dipanggil, bukan saat class diinisialisasi.
AbstractFactory

Untuk memahami AbstractFactory perhatikan gambar berikut



















public class LuxuryVehicleFactory extends VehicleFactory {
public Car getCar() {
return new LuxuryCar("L-C");
}
public SUV getSUV() {
return new LuxurySUV("L-S");
}
}

public class NonLuxuryVehicleFactory extends VehicleFactory {
public Car getCar() {
return new NonLuxuryCar("NL-C");
}
public SUV getSUV() {
return new NonLuxurySUV("NL-S");
}
}

public abstract class VehicleFactory {
public static final String LUXURY_VEHICLE = "Luxury";
public static final String NON_LUXURY_VEHICLE = "Non-Luxury";
public abstract Car getCar();
public abstract SUV getSUV();

public static VehicleFactory getVehicleFactory(String type) {
if (type.equals(VehicleFactory.LUXURY_VEHICLE))
return new LuxuryVehicleFactory();
if (type.equals(VehicleFactory.NON_LUXURY_VEHICLE))
return new NonLuxuryVehicleFactory();
return new LuxuryVehicleFactory();
}
}

Wednesday, September 2, 2009

JVM terminated. Exit code=-1

Have you ever got the above error message when you try to launch eclipse? Well it happened yesterday. When I started eclipse, it showed this error window



This error is quiet strange since I did fresh install jdk and eclipse on my windows machine. When I googled this error, there were some advices including to increase Xms512. But it did work before without setting anything. Then finally I found a good advice here : http://www.coderanch.com/t/423852/IDEs-Version-Control-other-tools/IRAD-JVM-Terminated-Exit-Code.

Yup. Remove the entries in eclipse.ini :). But unfortunately after you do that, there will be an error saying that you need to close your eclipse. To deal with this, you need to restore your eclipse.ini file (you can try another eclipse.ini file or just restore the last one) and change this :
-Xmx512m to Xmx256m.

People says that it happens because eclipse tries to allocate heap memory as much as 512 but it fails.
 

©2009 Stay the Same | by TNB