Selasa, 12 Juni 2012

Modul 6 - Behavioral Patterns (Chain of Responbility, Command Pattern)


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:
Dalam diagram di atas beberapa penjelasan diperlukan pada apa peran dari setiap kelas:
ü  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();

}
Output:
 

0 komentar:

Posting Komentar