Dalam buku tersebut terdapat 3 jenis pattern yang terdiri dari :
- Creational Pattern
- Abstract Factory
- Builder
- Factory Method
- Prototype
- Singleton
- Structural Pattern
- Adapter
- Bridge
- Composite
- Decorator
- Facade
- Flyweight
- Proxy
- 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 :
- https://sourcemaking.com/design-patterns-ebook
- Head First Design Pattern
- Wikipedia
- https://aryawiratama.wordpress.com/2012/01/13/design-pattern-strategy-pattern/
- https://sourcemaking.com/design_patterns/strategy/cpp/1
Semoga bermanfaat, terimakasih!