• Tidak ada hasil yang ditemukan

Implementasi

Dalam dokumen Buku Belajar Santai OOP PHP (Halaman 156-179)

Observer Pattern

I. Pengantar

Seperti namanya,observer patternberfungsi untuk melakukan ob- servasi terhadap suatuevent.Event yang dimaksud adalah sebuah interesting point dari suatu aplikasi. Dalamobserver pattern, jum- lahobserverbisa tidak terbatas.

Observer patternbiasanya digunakan untuk membuat sebuah ap- likasi dapat di-extendolehdeveloperlainnya tanpa harus melakukan perubahan padasource code. Cara ini biasanya disebuthooking.

Contoh penerapanobserver patternsangat banyak. Bila Anda nanti memutuskan untuk menggunakanframework, maka hampir semua framework menggunakanpattern ini. Biasanya dapatframework, Observer patterndisebut jugaevent dispatcher.

1 <?php 2

3 namespace ObserverPattern;

4

5 interface ObserverInterface 6 {

7 public function update(SubjectInterface $subject);

8 }

1 <?php 2

3 namespace ObserverPattern;

4

5 interface SubjectInterface 6 {

7 public function getName();

8

9 public function attach(ObserverInterface $observer);

10

11 public function detach(ObserverInterface $observer);

12

13 public function notify();

14

15 public function getState();

16 }

Observer

Observer Pattern 151

1 <?php 2

3 namespace ObserverPattern;

4

5 class Observer implements ObserverInterface 6 {

7 public function update(SubjectInterface $subject)

8 {

9 echo sprintf('Sekarang %s lagi %s', $subject->g\

10 etName(), $subject->getState()).PHP_EOL;

11 }

12 }

1 <?php 2

3 namespace ObserverPattern;

4

5 class OtherObserver implements ObserverInterface 6 {

7 public function update(SubjectInterface $subject)

8 {

9 echo sprintf('%s sedang %s', $subject->getName(\

10 ), $subject->getState()).PHP_EOL;

11 }

12 }

Subject

1 <?php 2

3 namespace ObserverPattern;

4

5 class Subject implements SubjectInterface 6 {

7 private $observers = array();

8

9 private $state;

10

11 private $name;

12

13 public function __construct($name)

14 {

15 $this->name = $name;

16 }

17

18 public function getName()

19 {

20 return $this->name;

21 }

22

23 public function attach(ObserverInterface $observer)

24 {

25 $this->observers[get_class($observer)] = $obser\

26 ver;

27 }

28

29 public function detach(ObserverInterface $observer)

30 {

31 $key = get_class($observer);

32 if (array_key_exists($key, $this->observers)) { 33 unset($this->observers[$key]);

34 }

35 }

Observer Pattern 153

36

37 public function notify()

38 {

39 foreach($this->observers as $observer) { 40 $observer->update($this);

41 }

42 }

43

44 public function update($state)

45 {

46 $this->state = $state;

47 $this->notify();

48 }

49

50 public function getState()

51 {

52 return $this->state;

53 }

54 }

composer.json

1 {

2 "autoload": { 3 "psr-4": { 4 "": ""

5 }

6 }

7 }

index.php

1 <?php 2

3 require __DIR__.'/vendor/autoload.php';

4

5 use ObserverPattern\Subject;

6 use ObserverPattern\Observer;

7 use ObserverPattern\OtherObserver;

8

9 $subject = new Subject('Mawar');

10

11 $observer = new Observer();

12 $otherObserver = new OtherObserver();

13

14 $subject->attach($observer);

15 $subject->attach($otherObserver);

16

17 $subject->update('Pergi ke kampus');

18 $subject->update('Pergi ke kantin');

19

20 $subject->detach($otherObserver);//$otherObserver tidak\

21 lagi ikut mengamati 22

23 $subject->update('Pulang kuliah');

Setelahcomposer update dan Anda menjalankan program diatas, maka hasilnya adalah sebagai berikut:

Observer Pattern

Bila Anda perhatikan, inti dariobserver patternada padamethod

Observer Pattern 155

update(), dimana pada method tersebut dipanggil juga method

notify().

1 public function update($state)

2 {

3 $this->state = $state;

4 $this->notify();

5 }

Disinilahchaning yang saya maksud diatas.

I. Pengantar

Factory patternadalah sebuahpatternyang bertujuan untuk melakukan sentralisasi dalam pembuatanobject. Sama sepertiobserver pattern, patternini juga banyak digunakan olehframework.

Keuntungan darifactory patternadalah ketika Anda perlu melakukan rename atau mengganti suatu classdalam factory pattern, Anda cukup menggantinya disatu tempat. Anda tidak perlu menggu- nakan fitursearch and replaceyang ada pada IDE atau Editor untuk mengetahui dimana sajaclasstersebut dipanggil.

II. Implementasi

Implementasifactory patternterbilang lebih mudah dibandingkan denganobserver patternyang sebelumnya. Untuk lebih jelas, per- hatikan contoh berikut:

Interface

156

Factory Pattern 157

1 <?php 2

3 namespace Factory;

4

5 interface KendaraanInterface 6 {

7 public function gas();

8 }

Factory

1 <?php 2

3 namespace Factory;

4

5 class Factory 6 {

7 protected $kendaraan;

8

9 public function __construct()

10 {

11 $this->kendaraan = array(

12 'sepeda' => Sepeda::class, 13 'motor' => Motor::class, 14 'mobil' => Mobil::class,

15 );

16 }

17

18 public function create($type)

19 {

20 if (!array_key_exists($type, $this->kendaraan))\

21 {

22 throw new \InvalidArgumentException(sprintf\

23 ('Kendaraan dengan tipe %s tidak ditemukan', $type));

24 }

25 $className = $this->kendaraan[$type];

26

27 return new $className();

28 }

29 }

Kendaraan

1 <?php 2

3 namespace Factory;

4

5 class Sepeda implements KendaraanInterface 6 {

7 public function gas()

8 {

9 return 'Wus wus wus...';

10 }

11 }

1 <?php 2

3 namespace Factory;

4

5 class Motor implements KendaraanInterface 6 {

7 public function gas()

8 {

9 return 'Brum... brum... brum...';

10 }

11 }

Factory Pattern 159

1 <?php 2

3 namespace Factory;

4

5 class Mobil implements KendaraanInterface 6 {

7 public function gas()

8 {

9 return 'Ngueeeeeeeennnnnnggggggggggggg';

10 }

11 }

composer.json

1 {

2 "autoload": { 3 "psr-4": { 4 "": ""

5 }

6 }

7 }

index.php

1 <?php 2

3 require __DIR__.'/vendor/autoload.php';

4

5 use Factory\Factory;

6

7 $factory = new Factory();

8 $sepeda = $factory->create('sepeda');

9 $motor = $factory->create('motor');

10 $mobil = $factory->create('mobil');

11

12 echo $sepeda->gas();

13 echo PHP_EOL;

14

15 echo $motor->gas();

16 echo PHP_EOL;

17

18 echo $mobil->gas();

19 echo PHP_EOL;

Bagaimana? Lebih simpel bukan? Bila kita jalankan program diatas maka hasilnya adalah sebagai berikut:

Factory Pattern

Facade Pattern

I. Pengantar

Facade Patternadalah sebuahpatternyang bertujuan untuk menyem- bunyikan kompleksitas sebuah proses.Patternini sangat terkenal pada pengguna framework Laravel digunakan pada core Laravel itu sendiri.

Keuntungan menggunakanpatternini adalahcalleratau pengguna tidak perlu mengetahui kompleksitas darisub system atau proses yang terjadi dalam internalmethod.

II. Implementasi

Dalam implementasi kali ini, kita akan membuat sebuah contoh yang cukup panjang. Kita akan membuatinterfaceserta beberapa classimplementasinya sebagai berikut:

Interface

161

1 <?php 2

3 namespace Facade;

4

5 interface CalculableInterface 6 {

7 public function setProduct(Product $product);

8

9 public function calculate();

10 }

• Implementasi

1 <?php 2

3 namespace Facade;

4

5 class Order implements CalculableInterface 6 {

7 /**

8 * @var Product

9 */

10 private $product;

11

12 /**

13 * @param Product $product

14 */

15 public function setProduct(Product $product)

16 {

17 $this->product = $product;

18 }

19

20 public function calculate()

21 {

Facade Pattern 163

22 // Anggap saja ini proses yang rumit dan panjang

23 }

24 }

1 <?php 2

3 namespace Facade;

4

5 class AdminFee implements CalculableInterface 6 {

7 /**

8 * @var Product

9 */

10 private $product;

11

12 /**

13 * @param Product $product

14 */

15 public function setProduct(Product $product)

16 {

17 $this->product = $product;

18 }

19

20 public function calculate()

21 {

22 // Anggap saja ini proses yang rumit dan panjang

23 }

24 }

1 <?php 2

3 namespace Facade;

4

5 class Discount implements CalculableInterface 6 {

7 /**

8 * @var Product

9 */

10 private $product;

11

12 /**

13 * @param Product $product

14 */

15 public function setProduct(Product $product)

16 {

17 $this->product = $product;

18 }

19

20 public function calculate()

21 {

22 // Anggap saja ini proses yang rumit dan panjang

23 }

24 }

1 <?php 2

3 namespace Facade;

4

5 class ShippingFee implements CalculableInterface 6 {

7 /**

8 * @var Product

9 */

Facade Pattern 165

10 private $product;

11

12 /**

13 * @param Product $product

14 */

15 public function setProduct(Product $product)

16 {

17 $this->product = $product;

18 }

19

20 public function calculate()

21 {

22 // Anggap saja ini proses yang rumit dan panjang

23 }

24 }

Product-nya

1 <?php 2

3 namespace Facade;

4

5 class Product 6 {

7 /**

8 * @var int

9 */

10 private $qty;

11

12 /**

13 * @var string

14 */

15 private $name;

16

17 /**

18 * @var int

19 */

20 private $price;

21

22 /**

23 * @return int

24 */

25 public function getQty()

26 {

27 return $this->qty;

28 }

29

30 /**

31 * @param int $qty

32 */

33 public function setQty($qty)

34 {

35 $this->qty = $qty;

36 }

37

38 /**

39 * @return string

40 */

41 public function getName()

42 {

43 return $this->name;

44 }

45

46 /**

47 * @param string $name

48 */

49 public function setName($name)

50 {

51 $this->name = $name;

Facade Pattern 167

52 }

53

54 /**

55 * @return int

56 */

57 public function getPrice()

58 {

59 return $this->price;

60 }

61

62 /**

63 * @param int $price

64 */

65 public function setPrice($price)

66 {

67 $this->price = $price;

68 }

69 }

Dariclass-classdiatas, kita akan membuatcallerdengan dua pen- dekatan. Pertama tanpa facade pattern dan kedua denganfacade pattern agar kelihatan perbedaannya. Untuk yang tidak menggu- nakanfacade pattern cukup mudah, berikut adalahcode pemang- gilnya.

1 <?php 2

3 require __DIR__.'/vendor/autoload.php';

4

5 use Facade\Product;

6 use Facade\AdminFee;

7 use Facade\Discount;

8 use Facade\Order;

9 use Facade\ShippingFee;

10

11 $product = new Product();

12 $product->setQty(1);

13 $product->setName('Facade Product');

14 $product->setPrice(10000);

15

16 $order = new Order();

17 $order->setProduct($product);

18 $order->calculate();

19

20 $discount = new Discount();

21 $discount->setProduct($product);

22 $discount->calculate();

23

24 $adminFee = new AdminFee();

25 $adminFee->setProduct($product);

26 $adminFee->calculate();

27

28 $shippingFee = new ShippingFee();

29 $shippingFee->setProduct($product);

30 $shippingFee->calculate();

Code diatas terlihat simple dan tidak ada masalah bukan? Tapi sebenarnya,codediatas bisa menjadi bermasalah jika dalam pener- apandiscountatau lainnya sudah mulai ada syarat-syarat tertentu sehingga akan banyakif nantinya disitu.

Dan semakin banyak if disana maka caller pun akan memiliki kompleksitas tinggi dan makin lama akan makin sulit di-maintain.

Untuk mengurangi kompleksitas pada pemanggil, maka kita bisa menggunakanfacade pattern. Dan berikut adalah contohnya:

Facade Class

Facade Pattern 169

1 <?php 2

3 namespace Facade;

4

5 class OrderFacade 6 {

7 private $order;

8

9 private $discount;

10

11 private $adminFee;

12

13 private $shippingFee;

14

15 public function __construct()

16 {

17 $this->order = new Order();

18 $this->discount = new Discount();

19 $this->adminFee = new AdminFee();

20 $this->shippingFee = new ShippingFee();

21 }

22

23 public function setProduct(Product $product)

24 {

25 $this->order->setProduct($product);

26 $this->discount->setProduct($product);

27 $this->adminFee->setProduct($product);

28 $this->shippingFee->setProduct($product);

29 }

30

31 public function createOrder()

32 {

33 //Ceritanya ada pengecekan ini dan itu 34

35 $this->order->calculate();

36 $this->discount->calculate();

37 $this->adminFee->calculate();

38 $this->shippingFee->calculate();

39

40 //Kompleks banget lah pokoknya

41 }

42 }

• Pemanggilnya

1 <?php 2

3 require __DIR__.'/vendor/autoload.php';

4

5 use Facade\Product;

6 use Facade\OrderFacade;

7

8 $product = new Product();

9 $product->setQty(1);

10 $product->setName('Facade Product');

11 $product->setPrice(10000);

12

13 $facade = new OrderFacade();

14 $facade->setProduct($product);

15 $facade->createOrder();

Pada code diatas, jika suatu saat ada perubahan syarat discount atau lainnya maka Anda tidak perlu merubahcodepada pemanggil.

Anda cukup merubahnya padaclassFacadeOrdersehingga kom- pleksitas pada pemanggil bisa dikurangi secara signifikan.

Code-code diatas ketika dijalankan memang tidak akan mengelu- arkan output apapun, namun yang ingin saya sampaikan adalah bahwa konsep facade pattern ini akan memudahkan kita ketika

Facade Pattern 171 menangani kompleksitas seperti pada prosescheckoutpada sistem e-commerce.

Bila biasa Anda menerapkan prinsip hajar bleh, maka dengan memahamifacade patternini, Anda dapat menerapkan solusi yang berbeda dan lebihmaintainable.

Sederhana

I. Pengantar

Setelah kita belajar tentang OOP hinggadesign pattern, maka saat- nya kita mencoba mengimplementasikan semua yang kita pelajari kedalam sebuah aplikasi yangreal.

Sebagaifinal project, kita akan membuat sebuahframeworkseder- hana berbasis OOP dan menggunakancomposersebagaimana yang telah kita pelajari sebelumnya.

Dalam dokumen Buku Belajar Santai OOP PHP (Halaman 156-179)

Dokumen terkait