6.1.Chain of responsibility
Dalam
menulis sebuah aplikasi dalam bentuk apapun, sering terjadi bahwa peristiwa
yang dihasilkan oleh satu objek perlu ditangani oleh objek yang satu lagi. Dan,
untuk membuat pekerjaan lebih sulit lagi, ketika terjadi penolakan akses ke
objek yang perlu menangani hal tersebut. Chain of responsibility pattern
memungkinkan objek untuk mengirim perintah tanpa tahu apa objek akan menerima
dan menanganinya. Permintaan yang dikirim dari satu objek ke objek lainnya
membuat bagian rantai dan setiap objek dalam rantai ini dapat menangani
perintah, menyebarkannya atau melakukan keduanya.
Berikut diagram UML untuk pola
Chain of Responsibility:
ü
Handler - mendefinisikan sebuah antarmuka untuk menangani
permintaan
ü
RequestHandler - menangani permintaan responsibility jika dapat menangani
permintaan ia melakukannya sendiri, jika tidak ia akan mengirimkan permintaan
untuk penggantinya
ü Client
- mengirimkan perintah ke objek pertama dalam rantai yang dapat menangani
perintah.
Contoh code Chain of responsibility dalam java:
using System;
namespace DoFactory.GangOfFour.Chain.Structural
{
class MainApp
{
static
void Main()
{
// Setup Chain of Responsibility
Handler h1 = new ConcreteHandler1();
Handler h2 = new ConcreteHandler2();
Handler h3 = new ConcreteHandler3();
h1.SetSuccessor(h2);
h2.SetSuccessor(h3);
// Generate and process request
int[] requests = { 2, 5, 14, 22, 18, 3, 27, 20 };
foreach (int request in requests)
{
h1.HandleRequest(request);
}
// Wait for user
Console.ReadKey();
}
}
abstract class Handler
{
protected
Handler successor;
public
void SetSuccessor(Handler
successor)
{
this.successor = successor;
}
public
abstract void
HandleRequest(int request);
}
class ConcreteHandler1 : Handler
{
public
override void
HandleRequest(int request)
{
if (request >= 0 && request < 10)
{
Console.WriteLine("{0}
handled request {1}",
this.GetType().Name, request);
}
else if (successor !=
null)
{
successor.HandleRequest(request);
}
}
}
class ConcreteHandler2 : Handler
{
public
override void
HandleRequest(int request)
{
if (request >= 10 && request < 20)
{
Console.WriteLine("{0}
handled request {1}",
this.GetType().Name, request);
}
else if (successor !=
null)
{
successor.HandleRequest(request);
}
}
}
/// <summary>
/// The 'ConcreteHandler3' class
/// </summary>
class ConcreteHandler3 : Handler
{
public
override void
HandleRequest(int request)
{
if (request >= 20 && request < 30)
{
Console.WriteLine("{0}
handled request {1}",
this.GetType().Name, request);
}
else if (successor !=
null)
{
successor.HandleRequest(request);
}
}
}
}
6.2. Command Pattern
Maksud dari pola ini adalah
membungkus permintaan dalam suatu objek, memungkinkan parameterisasi dari klien
dengan permintaan yang berbeda, memungkinkan menyimpan permintaan dalam
antrian.
Berikut diagram UML untuk pola
Chain of Responsibility:
Kelas-kelas
yang berpartisipasi dalam pola ini adalah:
·
Command -
menyatakan sebuah antarmuka untuk melaksanakan operasi;
·
ConcreteCommand
- memperluas antarmuka Command, menerapkan metode Execute dengan menerapkan
operasi yang sesuai pada Receiver. Ini mendefinisikan hubungan antara Kurator
dan tindakan.
·
Client
- membuat objek ConcreteCommand dan menetapkan penerima tersebut;
·
Invoker -
meminta perintah untuk melaksanakan permintaan tersebut;
·
Receiver
- tahu bagaimana melakukan operasi;
Client meminta perintah yang
akan dieksekusi. Invoker mengambil perintah, merangkum dan menempatkannya dalam
antrian, jika ada sesuatu yang lain untuk melakukan yang pertama, dan
ConcreteCommand yang bertanggung jawab atas perintah yang diminta, mengirim
hasilnya ke Receiver.
Contoh code Command pattern dalam C#:
#include
<iostream> #include <string> using namespace std;
class Person;
class Command
{
// 1. Create a class that encapsulates an object and a member function
// a pointer to a member function (the attribute's name is "method")
Person *object; //
void(Person:: *method)();
public:
Command(Person *obj = 0, void(Person:: *meth)() = 0)
{
object = obj; // the argument's name is "meth"
method = meth;
}
void execute()
{
(object-> *method)(); // invoke the method on the object
}
};
class Person
{
string name;
// cmd is a "black box", it is a method invocation
// promoted to "full object status"
Command cmd;
public:
Person(string n, Command c): cmd(c)
{
name = n;
}
void talk()
{
// "this" is the sender, cmd has the receiver
cout << name << " is talking" << endl;
cmd.execute(); // ask the "black box" to callback the receiver
}
void passOn()
{
cout << name << " is passing on" << endl;
// 4. When the sender is ready to callback to the receiver,
// it calls execute()
cmd.execute();
}
void gossip()
{
cout << name << " is gossiping" << endl;
cmd.execute();
}
void listen()
{
cout << name << " is listening" << endl;
}
};
int main()
{
// Fred will "execute" Barney which will result in a call to passOn()
// Barney will "execute" Betty which will result in a call to gossip()
// Betty will "execute" Wilma which will result in a call to listen()
Person wilma("Wilma", Command());
// 2. Instantiate an object for each "callback"
// 3. Pass each object to its future "sender"
Person betty("Betty", Command(&wilma, &Person::listen));
Person barney("Barney", Command(&betty, &Person::gossip));
Person fred("Fred", Command(&barney, &Person::passOn));
fred.talk();
}
class Person;
class Command
{
// 1. Create a class that encapsulates an object and a member function
// a pointer to a member function (the attribute's name is "method")
Person *object; //
void(Person:: *method)();
public:
Command(Person *obj = 0, void(Person:: *meth)() = 0)
{
object = obj; // the argument's name is "meth"
method = meth;
}
void execute()
{
(object-> *method)(); // invoke the method on the object
}
};
class Person
{
string name;
// cmd is a "black box", it is a method invocation
// promoted to "full object status"
Command cmd;
public:
Person(string n, Command c): cmd(c)
{
name = n;
}
void talk()
{
// "this" is the sender, cmd has the receiver
cout << name << " is talking" << endl;
cmd.execute(); // ask the "black box" to callback the receiver
}
void passOn()
{
cout << name << " is passing on" << endl;
// 4. When the sender is ready to callback to the receiver,
// it calls execute()
cmd.execute();
}
void gossip()
{
cout << name << " is gossiping" << endl;
cmd.execute();
}
void listen()
{
cout << name << " is listening" << endl;
}
};
int main()
{
// Fred will "execute" Barney which will result in a call to passOn()
// Barney will "execute" Betty which will result in a call to gossip()
// Betty will "execute" Wilma which will result in a call to listen()
Person wilma("Wilma", Command());
// 2. Instantiate an object for each "callback"
// 3. Pass each object to its future "sender"
Person betty("Betty", Command(&wilma, &Person::listen));
Person barney("Barney", Command(&betty, &Person::gossip));
Person fred("Fred", Command(&barney, &Person::passOn));
fred.talk();
}
Output:
Tidak ada komentar:
Posting Komentar