Pages

Selasa, 10 Juli 2012

Bridge Pattern

Bridge Pattern ini 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 (“nya” ditujukan untuk kelas abstrak).
Dalam sebagian besar tutorial, bridge pattern didefinisikan sebagai

pattern yang berusaha memisahkan antara abstraksi dan implementasi.
Bingung? Hehe.. Namanya juga teori, biasanya mengawang-awang jika tidak diaplikasikan. Yuk kita aplikasikan!
(Untuk contoh bridge pattern ini, saya ambil dari buku Design Patterns JAVA Workbook .)
Misalkan kita punya modal diagram kelas yang pada superclassnya terdapat sebuah kelas abstrak “MachineController”. Nah, di dalam MachineController ini terdapat beberapa abstract dan concrete method. Salah satu concrete method pada MachineController, yaitu inputfull, menggunakan hasil dari salah satu abstract method “getQueueMax()”.
public boolean inputfull(){
return getQueueMax() >= getQueue.size();

}
Dan selayaknya sebuah abstract method, method getQueueMax() ini baru akan didefinisikan dalam kelas yang turunan MachineController, yaitu StarPressController dan ShellController. Kedua kelas turunan ini mendefinisikan method getQueueMax() dengan cara yang berbeda. Berikut ini adalah diagram kelas yang dimaksudkan :
1
Sampai disini, masih baik-baik saja. 
Kemudian pada suatu hari, kita baru menyadari bahwa kita membutuhkan mekanisme (controller) yang berbeda pada untuk proses pengetesan.
Misalkan kita membutuhkan satu tambahan method pada kelas abstrak MachineController, yaitu method overflow(). Maka kita akan membuat sebuah kelas baru, kelas abstrak TestController, yang diturunkan dari kelas MachineController.
Sebagai kelas abstark, TestController membutuhkan StarPressController dan ShellController untuk mendefinisikan method abstrak getQueueMax(). Maka bentuk diagram kelas yang kita miliki sekarang adalah :
2
Dengan penambahan suatu mekanisme baru, maka bertambahlah tiga buah kelas pada diagram kelas kita. Bagaimana nanti jika kita akan menambahkan dua mekanisme baru? Berarti akan ada penambahan enam kelas baru! Bagaimana jika ada sepuluh mekanisme baru?! Begitu seterusnya hingga kelas-kelas ini beranak-pinak.
Keruwetan ini dapat ditangani oleh bridge pattern.
Langkah yang perlu dilakukan adalah :
  1. Buatlah sebuah interface yang berisi method-method abstrak dari superclass (MachineController).
  2. Untuk kelas-kelas yang mendefinisikan method abstrak dengan definisi yang berbeda, pindahkan letakkan dibawah interface. (implements)
  3. Kelas abstrak MachineController didefinisikan sebagai concrete class .
  4. Lakukan aggregasi! Buatlah sebuah atribut yang merupakan instans dari interface DriverController. Gunakan instans ini untuk mengakses method-method pada interface DriverController sebagai pengisi dari method konkrit, contohnya inputfull(). [Karena inputfull membutuhkan method getQueueMax()] Maka “bentuk” method inputfull() sekarang adalah :
public boolean inputfull(){
return driver.getQueueMax() <= driver.getQueue.getSize();

}
Dan diagram kelas kita sekarang adalah :
3
Nah, sekarang jika kita menginginkan mekanisme kontrol yang baru, tinggal membuat SEBUAH kelas yang diturunkan dari MachineController, semisal dengan TestController. Demikian pula jika suatu saat nanti kita membutuhkan tipe driver yang baru, maka kita tinggal menambah sebuah kelas yang mengimplementasikan DriverController, semisal dengan ShellDriver.
Inilah bridge pattern yang berhasil memisahkan (decouple) antara abstraksi dengan implementasinya. 
Dalam bukunya “Design Pattern Explained : A New Perspective on Object-Oriented Design”, Alan Shalloway dan James R. Trott menyatakan bahwa penurunan memang merupakan “surga” dalam pemrograman berbasis objek. Namun penggunaan penurunan kelas secara berlebihan akan menyulitkan pengembangan aplikasi di masa yang akan datang.

Setelah class diagram di atas, sekarang kita lanjutkan ke penerapannya pada sebuah script PHP seperti di bawah ini :
1
2 
3abstract class SaklarImplementasi {
4    abstract function status_awal($in_awal);
5    abstract function status_akhir($in_akhir);
6}
7 
8class SaklarKamar extends SaklarImplementasi {
9    function status_awal($status_awal_in) {
10      return '|||||'.$status_awal_in.'|||||';
11    }
12    function status_akhir($status_akhir_in) {
13      return '------'.$status_akhir_in.'------';
14    }
15}
16 
17class SaklarDapur extends SaklarImplementasi {
18    function status_awal($status_awal_in) {
19      return $status_awal_in;
20    }
21    function status_akhir($status_akhir_in) {
22      return strtoupper($status_akhir_in);
23    }
24}
25 
26class SaklarGarasi extends SaklarImplementasi {
27    function status_awal($status_awal_in) {
28      return 'garasi - '.$status_awal_in;
29    }
30    function status_akhir($status_akhir_in) {
31      return 'garasi - '.strtoupper($status_akhir_in);
32    }
33}
34 
35abstract class Saklar {
36    private $status_awal;
37    private $status_akhir;
38    private $kode;
39    function __construct($status_awal_in, $status_akhir_in, $kode_in) {
40      $this->status_awal = $status_awal_in;
41      $this->status_akhir  = $status_akhir_in;
42      if ($kode_in == 'dapur') {
43        $this->kode = new SaklarDapur();
44      } else if($kode_in == 'kamar') {
45        $this->kode = new SaklarKamar();
46      } else if($kode_in == 'garasi') {
47        $this->kode = new SaklarGarasi();
48      }
49    }
50    function status_awal() {
51      return $this->kode->status_awal($this->status_awal);
52    }
53    function status_akhir() {
54      return $this->kode->status_akhir($this->status_akhir);
55    }
56}
57 
58class SaklarHidup extends Saklar {
59    function hidupkan() {
60      return $this->status_awal() . " -> " . $this->status_akhir();
61    }
62
63 
64class SaklarMati extends Saklar {
65    function matikan() {
66      return $this->status_akhir() . ' -> ' . $this->status_awal();
67    }
68}
69  cetak('Lampu Kamar, mati -> hidup');
70  $saklar = new SaklarHidup('off','on','kamar');
71  cetak($saklar->hidupkan());
72  cetak('');
73 
74  cetak('Lampu Dapur, mati -> hidup');
75  $saklar = new SaklarHidup('off','on','dapur');
76  cetak($saklar->hidupkan());
77  cetak('');
78 
79  cetak('Lampu Kamar, hidup -> mati');
80  $saklar = new SaklarMati('off','on','kamar');
81  cetak($saklar->matikan());
82  cetak('');
83 
84  cetak('Lampu Dapur, hidup -> mati');
85  $saklar = new SaklarMati('off','on','dapur');
86  cetak($saklar->matikan());
87  cetak('');
88 
89  function cetak($isi) {
90    echo $isi."
"
;
91  }
92 ?>

0 komentar:

Posting Komentar