Kamis, 26 April 2012

Modul 3 - Structural Patterns (Adapter, Bridge, Composite)



3.1.  Adapter Pattern
Menurut Gang of Four, Adapter pattern digunakan untuk mengkonversi nama nama fungsi dan nama agar cocok dengan yang diinginkan oleh client (kelas yang akan menggunakan). Adapter memungkinkan kelas untuk bisa bekerja bersama sama walaupun sebelum tidak memungkinkan Karen a perbedaan nama nama fungsi dan variabel.
Class Diagram

 
Studi Kasus
Misalkan kita telah memiliki sebuah kelas lingkaran dalam desain aplikasi existing. Pada tahapan berikutnya muncul beberapa kelas baru yang yang hamper sejenis seperti garis, titik dan segiempat. Garis titik dan segiempat merupakan mengimplementasikan interface bidang_datar. Garis titik dan segiempat menshare beberapa fungsi seperti : tampil(), aturwarna(), sembunyikan(). Ketinya merupakan turunan dari kelas bidangdatar.
Kelas lingkaran merupakan kelas existing yang sebenarnya bukan turunan dari kelas bidang_datar karena pada saat kelas lingkaran ini dibuat kelas bidang_datar juga belum ada.  Celakanya adalah kelas lingkaran ini telah memiliki beberapa fungsi yang mirip tetapi namanya lain misal untuk menampilkan nama fungsinya display(), menyembunyikan hide() dan mengeset warna setcolor()
Pada tahap ini ada 2 solusi yang mungkin bisa dilakukan :
§  Mengubah isi kelas lingkaran dengan mengubah kelas lingkaran menjadi turunan dari kelas bidang_datar dan mengubah nama nama fungsi milik lingkaran sesuai dengan nama nama fungsi yang telah dideklarasikan di kelas bidang_datar sebagai induknya. Solusi ini merupakan pilihan yang buruk karena 2 hal pertama karena belum tentu kita mendapatkan source code kelas lingkaran. Kedua karena mengunah kode program selalu menghasilkan error baru, ingat bahwa kelas lingkaran adalah kelas eksisting yang barangkali sudah ada kelas lain yang menginstansiasi dan memanggil fungsi fungsi asli milik kelas ini sehingga ketika diganti mungkin akan menimbulkan error di berbagai tempat lain kode program kita.
§  Membuat sebuah kelas baru yang merupakan implementasi dari kelas bidang_datar, kelas ini dapat mewakili kelas lingkaran misalkan diberi nama lingkaran_new. Lingkaran_new sebagai turunan dari kelas bidang_datar akan mewarisi semua fungsi milik bidang_datar yaitu : tampil(), aturwarna() dan sembunyikan().  Agar kelas ini dapat memanfaatkan semua resource (kode program) yang telah ada di kelas lingkaran asli (existing) maka di buat kelas ini memiliki salah satu atribut yang bertipe lingkaran. Isi fungsi tampil adalah mengeksekusi fungsi display milik kelas lingkaran yang asli demikian juga dengan fungsi fungsi yang lain.
Perhatikan desain di bawah ini : 
 Solusi menggunakan adapter pattern :
Contoh Program dalam C#:
public class main {
    private bidang_datar mbidang_datar;
    public main () {
        mbidang_datar = new Adapter();
        mbidang_datar.setwarna();
        mbidang_datar.tampil();
        mbidang_datar.sembunyi();
        mbidang_datar = new segi4();
        mbidang_datar.setwarna();
        mbidang_datar.tampil();
        mbidang_datar.sembunyi();
    }
}

public class lingkaran {
    public lingkaran () {
    }
    public void display () {
    }
    public void setcolor () {
    }
    public void hide () {
    }
    public void specificRequest () {
    }
}

public class Adapter implements bidang_datar {
    private lingkaran mlingkaran;
    public void request () { 
    }
    public void tampil () {
     mlingkaran.display();
    }
    public void sembunyi () {
        mlingkaran.hide();
    }
    public void setwarna () {
        mlingkaran.setcolor();
    }
}
3.2.  Bridge Pattern

Bridge Pattern merupakan pattern yang kuat (powerfull) dan sering digunakan dalam pengembangan. Dan ini sebanding dengan usaha untuk mempelajarinya yang cukup menantang. Untuk memahami design pattern yang satu ini, kita perlu melihat makna decouple (tidak berpasangan), abstraction (abstraksi), dan implementation (implementasi) dari sisi yang berbeda terlebih dahulu. Decouple adalah bagaimana objek tidak terhubung satu sama lain, berdiri sendiri (independent), terpisah. Abstraksi adalah konsep bagaimana antar objek saling terhubung. Sedangkan “implementasi” janganlah dipandang sebagai penurunan dari suatu kelas abstrak (concrete class). Pandanglah “implementasi” sebagai objek lain yang digunakan oleh kelas abstrak (dan turunannya) untuk mengimplementasi dirinya (untuk kelas abstrak). Dalam sebagian besar tutorial, bridge pattern didefinisikan sebagai pattern yang berusaha memisahkan antara abstraksi dan implementasi.

Pola bridge berlaku ketika ada kebutuhan untuk menghindari mengikat permanen antara abstraksi dan sebuah implementasi dan ketika abstraksi dan implementasi perlu bervariasi secara independen. Menggunakan pola jembatan akan meninggalkan kode klien tidak berubah dengan tidak perlu mengkompilasi ulang kode.
Maksud dari pola ini adalah untuk memisahkan abstraksi dari implementasi sehingga dua dapat bervariasi secara independen. Diagram UML kelas untuk Pola Bridge:
 
Class peserta dalam pola bridge adalah:
1.     Abstraksi - Abstraksi mendefinisikan antarmuka abstraksi.
2.     AbstractionImpl - Mengimplementasikan interface abstraksi menggunakan referensi ke obyek Implementor jenis.
3.     Pelaksana - Implementor mendefinisikan antarmuka untuk kelas implementasi. Interface ini tidak perlu sesuai langsung ke antarmuka abstraksi dan bisa sangat berbeda. Imp abstraksi menyediakan implementasi dalam hal operasi yang disediakan oleh antarmuka Implementor.
4.     ConcreteImplementor1, ConcreteImplementor2 - Mengimplementasikan interface Implementor.
Contoh code dalam Java:
class Node {
    public int  value;
    public Node prev, next;
    public Node( int i ) { value = i; }
}

class StackArray {
    private int[] items = new int[12];
    private int   total = -1;
    public void push( int i ) { if ( ! isFull()) items[++total] = i; }
    public boolean isEmpty()  { return total == -1; }
    public boolean isFull()   { return total == 11; }
    public int top() {
        if (isEmpty()) return -1;
        return items[total];
    }
    public int pop() {
        if (isEmpty()) return -1;
        return items[total--];
}   }

class StackList {
    private Node last;
    public void push( int i ) {
        if (last == null)
            last = new Node( i );
        else {
            last.next = new Node( i );
            last.next.prev = last;
            last = last.next;
    }   }
    public boolean isEmpty() { return last == null; }
    public boolean isFull()  { return false; }
    public int top() {
        if (isEmpty()) return -1;
        return last.value;
    }
    public int pop() {
        if (isEmpty()) return -1;
        int ret = last.value;
        last = last.prev;
        return ret;
}   }

class StackFIFO extends StackArray {
    private StackArray temp = new StackArray();
    public int pop() {
        while ( ! isEmpty())
            temp.push( super.pop() );
        int ret =  temp.pop();
        while ( ! temp.isEmpty())
            push( temp.pop() );
        return ret;
}  }

class StackHanoi extends StackArray {
    private int totalRejected = 0;
    public int reportRejected()   { return totalRejected; }
    public void push( int in ) {
        if ( ! isEmpty()  &&  in > top())
            totalRejected++;
        else super.push( in );
}   }

class BridgeDisc {
    public static void main( String[] args ) {
        StackArray[] stacks = { new StackArray(), new StackFIFO(), new StackHanoi() };
        StackList    stack2 = new StackList();
        for (int i=1, num; i < 15; i++) {
            stacks[0].push( i );
            stack2.push( i );
            stacks[1].push( i );
        }
        java.util.Random rn = new java.util.Random();
        for (int i=1, num; i < 15; i++)
            stacks[2].push( rn.nextInt(20) );
        while ( ! stacks[0].isEmpty())
            System.out.print( stacks[0].pop() + "  " );
        System.out.println();
        while ( ! stack2.isEmpty())
            System.out.print( stack2.pop() + "  " );
        System.out.println();
        while ( ! stacks[1].isEmpty())
            System.out.print( stacks[1].pop() + "  " );
        System.out.println();
        while ( ! stacks[2].isEmpty())
            System.out.print( stacks[2].pop() + "  " );
        System.out.println();
        System.out.println( "total rejected is "
            + ((StackHanoi)stacks[2]).reportRejected() );
}   }

Hasil Compiling :
 

3.3.  Composite pattern

Composit Pattern adalah saat satu object yang merupakan sebuah collection, yang isinya antara lain adalah object- object yang collection juga, dan mempunyai sifat yang sama dengan si parent tadi. jadi terjadi proses rekursif disini. Keuntungannya: kita bisa memperlakukan keseluruhan collection seakan- akan sebagai satu object saja. Salah satu contoh aplikasi semisal, Microsoft Office Visio memungkinkan pengguna untuk dapat membuat berbagai bentuk semisal kotak, lingkaran, dan sebagainya. Kemudian pengguna dapat melakukan grouping terhadap bentuk-bentuk yang ada dan ketika group tersebut dipindahkan posisinya, otomatis semua shape yang ada dalam group tersebut ikut berpindah posisinya. Pengguna juga dapat melakukan grouping kembali terhadap group shape yang ada dengan shape-shape yang lain sehingga dapat terbentuk semacam hierarki pada shape yang ada. Bentuk-bentuk permasalahan semacam inilah yang dapat diselesaikan dengan Composite Pattern.

Dalam pemrograman, komposit digunakan ketika berhadapan dengan struktur pohon. Hal ini  sendiri adalah cukup sebuah konsep abstrak. Salah satu contoh komposit yang Anda lihat sehari-hari adalah sistem menu, dimana menu bar memiliki menu memiliki menu banyak, yang sendiri dapat memiliki submenu. Apa pun yang dapat dimodelkan sebagai struktur pohon dapat dianggap sebagai contoh komposit, seperti bagan organisasi.
Pola Komposit
Komposit ini dikenal sebagai pola struktural, karena itu digunakan untuk membentuk struktur objek besar di seluruh objek yang berbeda banyak. Definisi Komposit disediakan
Gang of Four  buku tentang Desain Pola menyatakan: Memungkinkan Anda untuk menyusun objek ke dalam struktur pohon untuk mewakili bagian-keseluruhan hirarki. Komposit memungkinkan klien memperlakukan objek

 
Dalam bentuk yang paling sederhana, kita bisa memikirkan komposit sebagai koleksi benda-benda, di mana salah satu dari benda itu sendiri bisa menjadi komposit, atau benda sederhana. Mari kita  lihat definisi diagram sebelum kita pergi ke lebih rinci. Antarmuka Komponen mendefinisikan antarmuka bahwa semua benda dalam sistem terdiri perlu menggunakan, apakah mereka daun (obyek sederhana) atau komposisi. Namun, hal ini biasanya diimplementasikan sebagai kelas abstrak menyediakan beberapa perilaku default dari pengaya, keluarkan dan metode getChild.

Daun tidak memiliki anak, dan sebagai kebutuhan-satunya untuk menerapkan metode operasi. Komposit perlu berbuat lebih banyak, karena juga mengandung komponen. Komposit akan lebih dari
mungkin perlu untuk mengimplementasikan metode operasi, yang dianggap sebagai operasi Daun terkait. Kadang-kadang ini mungkin tidak masuk akal untuk komposit untuk diterapkan. Biasanya, Komposit akan menerapkan metode dengan mendelegasikan kepada anak-anak. Klien hanya menggunakan antarmuka Komponen untuk memanipulasi objek.

Pola ini harus digunakan bila Anda ingin mewakili objek secara hierachical, atau Anda perlu objek dan komposit untuk diperlakukan secara seragam. Kerangka grafis adalah penggunaan paling umum dari pola ini. Objek dasar Grafis menyediakan kelas dasar untuk semua objek grafis lainnya, seperti Line, Rectangle, yang menyediakan implementasi sendiri dari cat () / gambar () method. Pola Komposit sering digunakan untuk representasi pohon sintaks abstrak.

Contoh Code Komposit dalam java:
//Component interface
public interface Graphic
{
public void add(Graphic g);
public void remove(Graphic g);
public Graphic get(int index);
public void paint();   
}
Berikutnya, kita akan mengimplementasikan interface ini untuk objek CompositeGraphic. Titik kunci untuk dicatat di sini adalah bahwa itu cat delegasi metode lukisan dengan objek anak:
//Composite
public class CompositeGraphic implements Graphic
{
private List<Graphic> children = new ArrayList<Graphic>();
public void paint()
{
//run the paint operation for each child
for(Graphic g: children)
{
g.paint();
}
}
public void add(Graphic g)
{
children.add(g);
}
public void remove(Graphic g)
{
if(children.contains(g))
{
children.remove(g);
}
}
public Graphic get(int index)
{
if(index < children.size())
{
return children.get(index);
}
}
Daun, dalam hal ini SimpleGraphic kasus, tidak dapat berisi grafik lain, sehingga tidak perlu untuk mengimplementasikan operasi list. Yang paling penting ini adalah bahwa ia menyediakan implementasi konkret dari cat () metode:
//Leaf
public class SimpleGraphic implements Graphic
{
public void paint()
{
//run the paint operation
}
/**
* Because we have no children, these operations will do nothing
**/
public void add(Graphic g)
{
//unsupported operation
}
public void remove(Graphic g)
{
//unsupported operation
}
public void get(int index)
{
//unsupported operation
}
 


0 komentar:

Posting Komentar