الگوهای طراحی: الگوی نما (Facade)

زمانی که به موضوع الگوهای طراحی می پردازیم، شاید برای شما سوالاتی پیش بیاید:

چرا ما بهتره از الگوهای طراحی در برنامه نویسی استفاده کنیم؟ واین در حالیه که کدهای ما بدون اونها هم به خوبی کار می کنند.

.خب، حالا سوال متقابل من این است که: "ترجیح می دهید در کجا زندگی کنید؟ در یک خانه لوکس یا در یک چهار دیواری؟ با اینکه می توان به هر دوی آنها مسکن اطلاق کرد"

مسلما ما خانه لوکس را ترجیح می دهیم زیرا امکانات بهتری را در اختیار ما قرار می دهد و همچنین نیاز کمتری به تعمیر و نگهداری دارد با اینکه تعمیر و نگهداری آن زحمت کمتری را می طلبد زیرا تمامی امکانات در آن لحاظ شده است.

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

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

در سر تا سر این آموزش، من زبان برنامه نویسی PHP را به عنوان زبان پایه برای ارائه مثال های الگوهای طراحی استفاده خواهم کرد. هر چند که الگوهای طراحی خود دقیقا بعنوان مفهوم هستند که می توان با استفاده از تمامی زبان های برنامه نویسی آنها را پیاده سازی نمود. و در رابطه با مثال های این آموزش شما تنها نیاز به تغییر دستور نحوی به زبان مورد نظرتان را خواهید داشت.

قواعد طراحی به 4 دسته تقسیم می شوند:

  • الگوهای ایجادی (creational patterns)
  • الگوهای ساختاری (structural patterns)
  • الگوهای رفتاری (behavioral patterns)
  • الگوهای همروندی (concurrency patterns)

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

الگوی طراحی نما(Facade)

UML الگوی طراحی نما

UML الگوی طراحی نما

مشکل

خب، فرض کنید که شما چندین عملیاتی را دارید که می خواهید به ترتیب انجام شوند، واینکه یک عمل(Action) یکسان هم در مکان های مختلف برنامه شما مورد نیاز است و بلطبع کدهای این عمل یکسان در مکان های مختلف برنامه شما قرار خواهند داشت. اما پس از چند روز شما نیاز به انجام تغییراتی در همان کدها را خواهید داشت.

آیا متوجه مشکل شدبد؟ ما باید این تغییرات یکسان و مشابه را در مکان های مختلفی که آن کدها در آنجا قرار دارند را انجام دهیم. آیا این زجر آور نیست؟

راه حل

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

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

مثال

اجازه دهید برای روشن شدن موضوع یک مثالی را ذکر کنیم. فرض کنید که وظیفه برنامه ریزی مراسم ازدواج یکی از دوستانتان با شما داده شده است. حجم کارهایی را که باید انجام شود را تصور کنید. حال اگر تمامی کارها را خود به تنهایی بخواهید انجام دهید. خب بلطبع باعث می شود که درصد خطا بیشتر شود و همچنین ممکن است کارهایی را از قلم بیاندازید و در نتیجه مراسم ازدواج دوستتان به هم بریزد.

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

در اینجا، شما نقش یک مشتری (Client) که کار شروع این پروسه را به عهده دارد و برنامه ریز مراسم ازدواج بعنوان یک (Facade) برای شما کار خواهد کرد، یعنی کامل کردن کارها بر اساس جهت و خواسته ای که شما تعیین می کنید.

مثالی با کدنویسی

در این بخش ما یک مثال بیشتری را که در رابطه با پیاده سازه الگوی طراحی نما (Facade) که با موضوع پروسه خرید یک محصول که البته برای وب سایت ها خیلی معمول و مرسوم است و همراه با مقداری کدنویسی است را با هم مرور می کنیم. اما قبل از اینکه ما بخواهیم به طور کامل کدهای پیاده سازی شده با الگوی طراحی نما را بررسی کنیم اجازه دهید کدی را مرور کنیم که دارای یک مشکل است.

یک پروسه ساده خرید یک کالا دارای گام های زیر است:

  1. افزودن کالا به سبد.
  2. محاسبه هزینه حمل و نقل.
  3. محاسبه تخفیف.
  4. ایجاد سفارش.

مشکل

// پروسه ساده خرید
$productID = $_GET['productId'];

$qtyCheck = new productQty();

if($qtyCheck->checkQty($productID) > 0) {

  // افزودن کالا به سبد
	$addToCart = new addToCart($productID);
	
	// محاسبه هزینه حمل و نقل
	$shipping = new shippingCharge();
	$shipping->updateCharge();
	
	// محاسبه تخفیف
	$discount = new discount();
	$discount->applyDiscount();
	
	$order = new order();
	$order->generateOrder();
}

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

راه حل

حال می خواهیم همین روند خرید را به روش الگوی طراحی نما (Facade) پیاده سازی کنیم، که در اثر آن کدهای ما قابل نگاهداری وتوسعه پذیرتر خواهند بود.

class productOrderFacade {
	
	public $productID = '';
	
	public function __construct($pID) {
		$this->productID = $pID;
	}
	
	public function generateOrder() {
		
		if($this->qtyCheck() > 0) {
			
			// افزودن کالا به سبد
			$this->addToCart();
			
			// محاسبه هزینه حمل و نقل
			$this->calulateShipping();
			
			// محاسبه تخفیف
			$this->applyDiscount();
			
			// ایجاد سفارش
			$this->placeOrder();
			
		}
		
	}
	
	private function addToCart () {
		/* .. افزودن کالا به سبد ..  */
	}
	
	private function qtyCheck() {
		
		$qty = 'get product quantity from database';
		
		if($qty > 0) {
			return true;
		} else {
			return true;
		}
	}
	
	
	private function calulateShipping() {
		$shipping = new shippingCharge();
		$shipping->calculateCharge();
	}
	
	private function applyDiscount() {
		$discount = new discount();
		$discount->applyDiscount();
	}
	
	private function placeOrder() {
		$order = new order();
		$order->generateOrder();
	}
}

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

خب حالا لطفا به مقدار کدهایی که برای روند خرید لازم توجه کنید:

// نکته: برای جلوگیری از حملات تزریق SQL نباید مقادیر را بصورت مستقیم به بانک اطلاعاتی ارسال کنیم
$productID = $_GET['productId'];

//تنها 2 خط کد بجای دسته ای از کدها را می نویسیم
$order = new productOrderFacade($productID);
$order->generateOrder();

خب حال تصور کنید زمانی که بخواهید تغییراتی را در روند خرید انجام دهید تنها کافیست این تغییرات را در کلاس نمای آن که ساخته بودیم انجام دهید بجای آنکه در مکان های مختلف کدهایتان این تغییرات مشابه را انجام دهید.

نتیجه گیری

به عبارت ساده می توان گفت زمانی باید از الگوی طراحی نما (Facade) استفاده کنید که شما نیاز به یک رابط برای اتمام چندین رویه (کار) داشته باشید، همانطوری که در مثال مراسم ازدواج زده شد که برنامه ریز مراسم که به عنوان الگوی نما (Facade) برای شما عمل می کرد تا شما چندین کار بطور کامل انجام دهید.



بومیم