18 مهر 1398 ساعت 14:11

آموزش الگوی طراحی Adapter به همراه نمونه کد و دانلود سورس

بطور کلی یکی از مهمترین دلایل استفاده از الگوی طراحی Adapter زمانی می باشد که شما نیاز به تغییر در کارکرد خود دارید اما می خواهید که در کدهای اصلی و پایه هیچ تغییری ایجاد نکنید.

الگوی های طراحی یا design pattern ها، کتابخانه یا چارچوب خاصی نیستد، در حقیقت الگوی های طراحی روش هایی هستند که برای ارتباط بین اشیاء و کلاس ها و رفع یک مشکل کلی در زمینه طراحی ایجاد شده اند. 

الگوی های طراحی روش هایی هستند که توسط دیگر برنامه نویس ها در طول سالها ایجاد شده و شما می توانید در موقعیت های مناسب از این الگوها برای افزایش سرعت توسعه و کد نویسی خود استفاده کنید. البته باید بسیار مراقب باشید که از یک الگو در جای نا مناسب استفاده نکنید تا با مشکلات بعدی مواجه نشوید. پس می توان گفت که الگوی های طراحی علاوه بر اینکه به سرعت توسعه کمک می کنند، اگر در جای مناسب خود استفاده نشوند ممکن است باعث کند شدن توسعه سیستم نیز شوند.

در حال حاضر بیش از ۲۰ الگوی طراحی شناخته شده وجود دارد که در سه دسته زیر تقسیم می شوند:

الگوی های Creational

الگوی های Behavioral

الگوی های Structural

در این مطلب ما در مورد الگوی طراحی آدپتور Adapter  که در دسته ی Structural قرار دارد صحبت خواهیم کرد، الگوی  طراحی آدپتور همانطور که از نامش پیداست مانند یک آدپتور در زندگی حقیقی ما، یک چیز را به موارد دیگری تبدیل می کند. برای نمونه آدپتور موبایل خود را تصور کنید، این آدپتور برق 220 ولت را به چیزی کمتر از ۱۰ ولت تبدیل می کند تا برای موبایل قابل استفاده باشد! و به این صورت لازم نیست ما موبایل خود را با برق ۲۲۰ هماهنگ کنیم! و به نوعی بدون تغییر در موبایل ما با استفاده از یک ادپتور برق لازم را آماده کرده ایم. در دنیای برنامه نویسی هم به همین صورت می باشد یعنب ما کلاس یا کلاس هایی داریم و می توانیم با استفاده از الگوی آدپتور از تغییر دادن این کلاس ها برای ورودی های متفاوت یا خروجی های متفاوت خودداری کنیم.

بطور کلی یکی از مهمترین دلایل استفاده از الگوی طراحی Adapter زمانی می باشد که شما نیاز به تغییر در کارکرد خود دارید اما می خواهید که در کدهای اصلی و پایه هیچ تغییری ایجاد نکنید.

در مهندسی نرم افزار، الگوی طراحی Adapter یک الگوی طراحی می باشد که اجازه می دهد تا کلاس موجود از  interface کلاس های دیگر استفاده نمایید . این باعث می شود که شما بتوانید کلاس های جدیدی را بدون ایجاد تغییر در کلاس های مادر بوجود آورید.

برای آشنایی بیشتر با این الگوی طراحی یک نمونه را با همدیگر حل خواهیم کرد:

فرض کنید ما کلاسی بنام Post داریم و میخواهیم همراه با ارسال یک مطلب یا همان Post یک توییت نیز ارسال شود. پس ما کلاس خود را بصورت زیر می سازیم:


// creating a post and posting to Twitter
$post              = new Post();
$post->description = 'My first post to Twitter. Just for fun!';
$post->url         = 'http://juniorgrossi.com';
$post->send();

// inside Post class
class Post
{
	// ... code and more code
	public function send()
	{
		$text = $this->description . ' ' . $this->url;
		// some Twitter class
		$twitter = new Twitter();
		// authenticate and more ...
		$twitter->tweet( $text );
	}
}

 

کد بالا بخوبی کار ما رو را می ندازه! اما چند ماه بعد ما تصمیم میگیرم که علاوه بر تویتر بتونیم توی اینستاگرام هم مطالمون رو ارسال کنیم! پس کد خودمون رو بصورت زیر تغییر می دیم:

<?php 
// changing the Post class
class Post
{
    public function send($service = 'twitter')
    {
        if ($service == 'twitter') {
            $twitter = new Twitter();
            // ...
            $twitter->tweet();
        } elseif ($service == 'instagram') {
            $instagram = new Instagram();
            // ...
            $instagram->postToInstagram();
        }
    }
}

 

خوب این کد هم به درستی کار می کنه.

اما!

بنظر شما کد بالا کمی زشت! حال بهم زن :| و غیر جذاب نیست:) ؟؟؟؟؟؟

خوب بدون شک جواب شما بله هست! اما چاره چیه؟ 

چاره ی این کار استفاده از الگوی طراحی آدپتور می باشد، در اینجا ما یک کلاس داریم (موبایل) و چندین نوع داده که می توان همان برق شهری، برق ماشین و... حساب کرد (البته با این حساب که برق ورودی هست و داده های ما خروجی :))))) ) خوب پس میایم و الگوی طراحی ادپتور رو بر روی کدهای خودمون اجرا می کنیم:

 

ابتدا یک interface بنام ServiceInterface ایجاد خواهیم کرد، کار این interface این هست که یک سری متد رو که ما لازم داریم توش قرار می دهیم و می گیم هر کلاسی که خواست با کلاس پست ما در اراتباط باشه و مطالب رو بفرسته روی شبکه های اجتماعی باید این اینترفیس رو implements کنه

interface  ServiceInterface{
	public function authenticate(array $options);
	
	public function post($text, $url);
}

این interface برای نمونه دارای دو متد هست که یکی کار احراز هویت و دیگری کار ارسال به شبکه اجتماعی رو برای ما انجام میده.

حال دو کلاس دیگه یعنی کلاس های TwitterService و InstagramService رو اینترفیس بالا رو پیاده سازی می کنن و بصورت زیر ایجاد می کنیم:

class TwitterService implements ServiceInterface
{
	protected $service;
	
	public function __construct()
	{
		$this->service = new Twitter();
	}
	
	public function authenticate(array $options)
	{
		$apiKey = $options['api_key'];
		// ...
		$this->service->authenticateUsingSomeMethod($apiKey);
		// ...
	}
	
	public function post($text, $url)
	{
		// ...
		$this->service->tweet($text . ' ' . $url);
		// ...
	}
}
class InstagramService implements ServiceInterface
{
	protected $service;
	
	public function __construct()
	{
		$this->service = new Instagram();
		$this->service->someAnotherMethodYouHaveToCall();
	}
	
	public function authenticate(array $options)
	{
		// ...
		$this->service->authenticateWithInstagramClass();
		// ...
	}
	
	public function post($text, $url)
	{
		// ...
		$this->service->postToInstagram($text);
		// ...
	}
	
}

همانطور که می بینید دو کلاس بالا هر دو، متدهای مربوط به اینترفیس را درون خودشون دارند که عملیات احراز هویت و ارسال رو قرار هست برای ما انجام بدن.

می بینید که در دو سرویس بالا دو کلاس Instagram و Twitter ایجاد شده اند. این کلاس ها در اصل مطابق با اصول هر شبکه ای اجتماعی عملیات های ارسال و احراز هویت رو برای ما انجام می دن و یک خروجی به سرویس می دن که از اون بتونیم استفاده کنیم.

حالا کلاس های Post, Instagram و Twitter روبصورت زیر ایجاد میکنم:

class Post
{
	protected $service;
	
	public function setServiceAdapter(ServiceInterface $service)
	{
		$this->service = $service;
	}
	
	public function send()
	{
		$this->service->post($this->description, $this->url);
	}
	
}
class Twitter
{
	public function authenticateUsingSomeMethod()
	{
	
	}
	
	public function tweet()
	{
	 echo 'Twitter';
	}
}
class Instagram
{
	public function someAnotherMethodYouHaveToCall()
	{
	
	}
	
	public function authenticateWithInstagramClass()
	{
	
	}
	
	public function postToInstagram()
	{
		ECHO 'INSTA';
	}
}

کلاس Post ما دارای دو متد می باشد:

setServiceAdapter: کار این متد این هست که یک سرویس که اینترفیس ServiceInterface رو پیاده سازی کرده باشه رو دریافت می کنه و اون رو به در property یا متغیر $service قرار میده.

send: این متد نیز با توجه به سرویس وارد شده متد post سرویس را صد زده و عملیات ارسال را انجام خواهد داد.

در نهایت می توانید کلاس های خود را بصورت زیر ایجاد و تست کنید:

// creating a post and posting to Twitter, Instagram or Facebook
$post = new Post();

// if want to use Twitter
$post->setServiceAdapter(new TwitterService()); // OR
// if want to use Instagram
$post->setServiceAdapter(new InstagramService()); // OR maybe

$post->description = 'My first post to Twitter. Just for fun!';
$post->url = 'http://juniorgrossi.com';

$post->send();

 

فایل مربوط به این پروژه در پایین همین مطلب پیوست شده است که می توانید دانلود و به راحتی اجرا و نتیجه را مشاهده نمایید.

توجه: درصورت دانلود فایل ها حتما دستور composer install را یک بار در خط فرمان سیستم خود اجرا نمایید تا فایل مربوط به autoload دریافت شود.

 

درصورتی که سوال یا پیشنهادی دارید از بخش نظرات برای ما ارسال نمایید.

92 admin
نظرات

برای اطلاع از پاسخ به نظر شما می توانید ایمیل یا شماره موبایل خود را وارد نمایید. *

ایمیل و شماره موبایل شما کاملا مخفی خواهد ماند و در سایت نمایش داده نخواهد شد. *

پاسخ به نظر
اگر نظری برای این مطلب ارسال شد از طریق ایمیل مرا اطلاع بده!

هنوز برای این مطلب نظری ارسال نشده است!
0