Sunday, 27 November 2016

ABOUT STRATEGY PATTERN

Design Pattern pertama kali diperkenalkan Gang of Four yang terdiri dari Erich GammaRichard HelmRalph Johnson, dan John Vlissides dalam bukunya yang berjudul Design Pattern : Elements of Reusable Object – Oriented Software pada tahun 1995. Buku tersebut menjelaskan bahwa design pattern merupakan sekumpulan solusi – solusi umum yang sering digunakan oleh para ahli desainer object – oriented software. Design pattern muncul berdasarkan pengalaman mereka yang sering menghadapi masalah yang sama dengan penyelesaian yang sama secara berulang – ulang. Nah solusi – solusi yang sering muncul inilah dirangkum oleh GoF  (Gang of Four) kedalam buku tersebut dan dinamakan design pattern. Dengan design pattern kita juga bisa berkomunikasi lebih mudah dengan programmer lain, cukup dengan mengatakan nama patternnya maka kita sudah paham desain apa yang dimaksud. Kemudian design pattern tidak sama dengan algoritma, karena design pattern lebih mengarah ke solusi bukan implementasi seperti algoritma.

Dalam buku tersebut terdapat 3 jenis pattern yang terdiri dari :


  1. Creational Pattern
    • Abstract Factory
    • Builder
    • Factory Method
    • Prototype
    • Singleton
  2. Structural Pattern
    • Adapter
    • Bridge
    • Composite
    • Decorator
    • Facade
    • Flyweight
    • Proxy
  3. Behavioral Pattern
    • Chain of Responsibility
    • Command
    • Interpreter
    • Iterator
    • Mediator
    • Memento
    • Observer
    • State
    • Strategy
    • Template Method
    • Visitor

Dari sekian banyak design pattern yang ada, pada kesempatan kali ini saya akan berfokus menguraikan mengenai strategy pattern.

Strategy pattern digunakan untuk mengelompokkan sejumlah algoritma, mengenskapsulasinya menjadi sebuah objek, dimana nantinya kita bisa mempertukarkan objek tersebut. Hal ini berarti kita dapat merubah atau mempertukarkan algoritma tersebut secara dinamis pada saat aplikasi sedang berjalan. Strategy pattern sangat membantu dalam memelihara kode program, karena ketika kita memiliki banyak algoritma maka aplikasi akan semakin kompleks dan tentu saja akan sangat sulit memelihara kode program kita. Lagi pula dengan mengenkapsulasi algoritma mejadi sebuah kelas, kita bisa menggunakan algoritma tersebut kapan pun bila dibutuhkan.

Struktur strategy pattern digambarkan menggunakan UML adalah sebagai berikut.



Bayangkan kita memiliki banyak cara (algoritma) untuk menyelesaikan suatu masalah yang kompleks dimana tidak semua cara bisa digunakan, namun lebih cenderung bergantung kondisi pada saat aplikasi sudah berjalan (Runtime). Jadi pada saat runtime tidak semua cara bisa digunakan mungkin hanya satu atau dua saja dari sekian banyak cara yang kita miliki. Nah untuk lebih mudahnya saya sertakan contoh sederhana penggunaan strategy pattern. Contoh ini diadaptasi dari buku Head First Design Pattern.
Berikut adalah implementasi sederhana strategy pattern 




Interface senjata dan beberapa kelas implementasinya merupakan sekumpulan algoritma yang nantinya bisa digunakan oleh karakter seperti kelas Raja dan kelas Prajurit. Kita bisa merubah behavior pada kelas Raja dan prajurit secara dinamis pada saat runtime, karena saya telah menyediakan method
Jadi kita bisa mengganti atau mempertukarkan senjata yang digunakan baik oleh Raja maupun Prajurit. 

Untuk lebih jelasnya berikut contoh terlampir berupa sorce code dalam bahasa c++ :

 #include <iostream.h>  
 #include <fstream.h>  
 #include <string.h>  
 class Strategy;  
 class TestBed  
 {  
  public:  
   enum StrategyType  
   {  
     Dummy, Left, Right, Center  
   };  
   TestBed()  
   {  
     strategy_ = NULL;  
   }  
   void setStrategy(int type, int width);  
   void doIt();  
  private:  
   Strategy *strategy_;  
 };  
 class Strategy  
 {  
  public:  
   Strategy(int width): width_(width){}  
   void format()  
   {  
     char line[80], word[30];  
     ifstream inFile("quote.txt", ios::in);  
     line[0] = '\0';  
     inFile >> word;  
     strcat(line, word);  
     while (inFile >> word)  
     {  
       if (strlen(line) + strlen(word) + 1 > width_)  
        justify(line);  
       else  
        strcat(line, " ");  
       strcat(line, word);  
     }  
     justify(line);  
   }  
  protected:  
   int width_;  
  private:  
   virtual void justify(char *line) = 0;  
 };  
 class LeftStrategy: public Strategy  
 {  
  public:  
   LeftStrategy(int width): Strategy(width){}  
  private:  
    /* virtual */void justify(char *line)  
   {  
     cout << line << endl;  
     line[0] = '\0';  
   }  
 };  
 class RightStrategy: public Strategy  
 {  
  public:  
   RightStrategy(int width): Strategy(width){}  
  private:  
    /* virtual */void justify(char *line)  
   {  
     char buf[80];  
     int offset = width_ - strlen(line);  
     memset(buf, ' ', 80);  
     strcpy(&(buf[offset]), line);  
     cout << buf << endl;  
     line[0] = '\0';  
   }  
 };  
 class CenterStrategy: public Strategy  
 {  
  public:  
   CenterStrategy(int width): Strategy(width){}  
  private:  
    /* virtual */void justify(char *line)  
   {  
     char buf[80];  
     int offset = (width_ - strlen(line)) / 2;  
     memset(buf, ' ', 80);  
     strcpy(&(buf[offset]), line);  
     cout << buf << endl;  
     line[0] = '\0';  
   }  
 };  
 void TestBed::setStrategy(int type, int width)  
 {  
  delete strategy_;  
  if (type == Left)  
   strategy_ = new LeftStrategy(width);  
  else if (type == Right)  
   strategy_ = new RightStrategy(width);  
  else if (type == Center)  
   strategy_ = new CenterStrategy(width);  
 }  
 void TestBed::doIt()  
 {  
  strategy_->format();  
 }  
 int main()  
 {  
  TestBed test;  
  int answer, width;  
  cout << "Exit(0) Left(1) Right(2) Center(3): ";  
  cin >> answer;  
  while (answer)  
  {  
   cout << "Width: ";  
   cin >> width;  
   test.setStrategy(answer, width);  
   test.doIt();  
   cout << "Exit(0) Left(1) Right(2) Center(3): ";  
   cin >> answer;  
  }  
  return 0;  
 }  

Output

 Exit(0) Left(1) Right(2) Center(3): 2   
  Width: 75   
  Exit(0) Left(1) Right(2) Center(3): 3   
  Width: 75   


Kapan kita menggunakan strategy pattern ? Kita bisa menggunakan strategy pattern bila mengalami kondisi sebagai berikut :
  • Jika terdapat kelas yang saling berhubungan dan hanya dibedakan oleh behaviornya saja. Pada contoh diatas kelas Raja dan Prajurit memiliki keterkaitan karena memiliki kemiripan sifat. Namun yang membedakan adalah behaviornya saja, misalnya Raja menggunakan senjata Kapak dan Prajurit menggunakan senjata pedang.
  • Kita memiliki banyak algoritma yang harus diimplementasikan.
  • Kita ingin algoritma tersebut tidak tercampur dengan kode client.
  • Adanya sebuah kelas yang mendefinisikan banyak behavior dan behavior ini muncul karena adanya beberapa syarat yang harus dipenuhi. Misalnya saja jika pedang prajurit patah maka ia akan menggantinya dengan pisau.
Referensi :




Semoga bermanfaat, terimakasih!