The Adapter Design Pattern
Adapter Pattern বুজতে আপনার একদমই অসুবিধা হবে না কারণ আপনি জানেন Adapter Pattern কি । এখন হয়তো ভাবছেন আমি কিভাবে জানি । চলেন দেখি ।
আপনারা সবাই মেমরি কার্ড দেখে থাকবেন । যখন মেমরি কার্ড থেকে কোন ফাইল আপনার কম্পিউটার বা ল্যাপটপ Transfer করতে চান আর যখন দেখেন মেমরি কার্ড থেকে ফাইল Transfer করার মত কিছুই নেই কম্পিউটার বা ল্যাপটপ তখন নিশ্চয় আপনি কার্ড রিডার অথবা Adapter ব্যবহার করেছেন ।
কি বুঝো নাই ব্যাপারটা !!! আরে ব্যাপার না চলেন আরও একটা Example দেয়া যাক ।
ধরুন আপনি আপনার Laptop নিয়ে কোথায় ঘুরতে গেছেন । Laptop টা যখন চার্জ দিতে গেলেন, দেখলেন আপনার Laptop এর চার্জার পোর্ট তিন পিনের । আর যেখানে চার্জ দিবেন সেটার পোর্ট দুই পিনের তখন আপনি কি করবেন ??
নিশ্চয় একটা Adapter ইউজ করবেন । Adapter pattern ও একি রকম, ব্যতিক্রম কিছু না । তাহলে চলুন দেখি Adapter Pattern কিভাবে Implement করা যায় ।
শুরুতেই একটা Problem নিয়ে আলোচনা করি । ধরুন আপনার একটা website আছে এবং কিছু ইউজারও আছে তাদের Facebook ফ্রেন্ডস এবং কতগুলো পোস্ট করেছে সেটা জানতে চান । দেখা যাক তাহলে কিভাবে করা যায় ।
class Facebook
{
public function getFriends()
{
var_dump(“get all facebook friends”);
}
public function getPosts()
{
var_dump(“get all facebook posts”);
}
}
class Person
{
public function social( $social )
{
$social->getPosts();
$social->getFriends();
}
}
$person = new Person();
$person->social(new Facebook());
এইতো হয়ে গেছে, খুব সহজ না । কিন্তু এই মুহূর্তে আপানার বস এসে আপনাকে বলল উনি twitter -এর সকল Followers and Tweets ও জানতে চায় । এই শুনে আপনি হয়তো মনে মনে বলবেন আগে বলতে কি হয়ে..ছি..লো গো মনু । ধরে নিচ্ছি আপনি আবার একটু চালাক প্রকৃতির আপনি বুঝতে পারছেন যে সামনে আরও চেঞ্জ আসতে পারে । তাই এমন কিছু চাচ্ছেন যে সামনে এমন কিছু আবার আসলে আপনি যেন সহজে সামাল দিতে পারেন । আর সেই জন্যই মূলত আমরা আজকে Adapter Pattern শিখছি । চলেন স্টেপ বাই স্টেপ দেখি । শুরুতেই Twitter ক্লাস বানায় ফেলি ।
<?php
class Twitter
{
public function getFollowers()
{
var_dump("get Twitter followers");
}
public function getTweets()
{
var_dump("get all twitter tweets");
}
}
class Person
{
public function social( $social )
{
$social->getPosts();
$social->getFriends();
}
}
$person = new Person();
$person->social(new Facebook());
$person->social(new Twitter());
এখন রান করি । দেখা যাচ্ছে একটা ERROR । কারণ getPosts নামে Twitter ক্লাসে কোন মেথড নেই । এখানে শুধু মাত্র getPosts and getFriend মেথডই Allow করবে ।ধরে নেই Person ক্লাস আপনার পুরো web application এবং আপনি চাচ্ছেন না মেজর কিছু চেঞ্জ করতে । তাহলে কি করবেন ?? তাহলে যেটা করতে হবে Person ক্লাসের social মেথডটা একটা Contract এর মধ্যে নিয়ে আসতে হবে । যেমনঃ
interface SocialInterface
{
public function getFriends();
public function getPosts();
}
এবং Person ক্লাসের social মেথডটা শুধু মাত্র SocialInterface Contract ই Allow করবে । এইবার আমাদের আপডেটের কোড হবে এই রকম
<?php
interface SocialInterface
{
public function getFriends();
public function getPosts();
}
class Twitter
{
public function getFollowers()
{
var_dump("get Twitter followers");
}
public
function getTweets()
{
var_dump("get all twitter tweets");
}
}
class Person
{
public function social(SocialInterface $social)
{
$social->getPosts();
$social->getFriends();
}
}
$person = new Person();
$person->social(new Facebook());
$person->social(new Twitter());
আবার রান করি । আবারো Error কারণ twitter class সেই SocialInterface contract টা Follow করে না । এখন হয়তো মনে মনে আমাকে গালি দিচ্ছেন এতো কষ্ট ক্যান করাইলেন পয়েন্ট আসেন ভাই পয়েন্টে ।
প্রতীক্ষার পালা শেষ হলো । এখন আমার Twitter — এর জন্য একটা Adapter লিখবো ।
// ... previous code ...
class TwitterAdapter implements SocialInterface
{
/**
* @var Twitter
*/
protected $twitter;
public function __construct(Twitter $twitter)
{
$this->twitter = $twitter;
}
public function getFriends()
{
$this->twitter->getFollowers();
}
public function getPosts()
{
$this->twitter->getTweets();
}
}
$person = new Person();
$person->social(new Facebook());
$person->social(new TwitterAdapter(new Twitter()));
দেখেন কত সহজে আমরা করে ফেললাম । কিন্তু আপানার বস এতেও সন্তুষ্ট না যা আপনি আগেই জানতেন । তিনি এবার linkedin -এর সকল conections and feeds জানতে চাচ্ছে । কিন্তু আপনার টেনশন নেয়ার কোন কারণ নেই । কারণ পুরো Application এর কোথাও আপনাকে চেঞ্জ করতে হবে না । অবাক হওয়ার কোন কারণ নেই, কিভাবে করবো চলেন দেখে আসি ।
class LinkedInAdapter implements SocialInterface
{
/**
* @var LinkedIn
*/
protected $linkedIn;
public function __construct(LinkedIn $linkedIn)
{
$this->linkedIn = $linkedIn;
}
public function getFriends()
{
$this->linkedIn->getConnections();
}
public function getPosts()
{
$this->linkedIn->getFeeds();
}
}
class LinkedIn
{
public function getConnections()
{
var_dump("get all linkedin connections");
}
public function getFeeds()
{
var_dump("get all linkedin feeds");
}
}
// ... previous code ...
$person->social(new LinkedInAdapter(new LinkedIn()));
সো এই ছিল Basically Adapter Pattern । Adapter Pattern এর আরও Example দিতে চাইলে আপনি Multiple Payment Gateway দিয়ে কাজ করতে পারেন যা শুরুতে হয়তো একটা Payment Gateway নিয়ে কাজ করেছেন পরবর্তীতে আরো কিছু Payment Gateway সংযুক্ত করতে চাইলে । এছাড়া লারাভেলে কাজ করে থাকলে লারাভেল filesystem ও কিন্তু Adapter Pattern এ করা, চাইলে দেখে নিতে পারেন ।
Full Code পাবেন এইখানে ।
খুব ভালো করে লিখতে জানি না এবং খুব ভালো বুঝাতেও পারি নাহ তবু চেষ্টা করেছি এবং চেষ্টা করেই যাবো ইন শাহ্ আল্লাহ্ । সামনে আর কিছু Design Pattern নিয়ে লেখার ইচ্ছা আছে । ভালো থাকবেন আল্লাহ্ হাফেজ ।