در این آموزش قصد داریم تا با Template Design Pattern آشنا شویم و به بررسی کاربردهای آن در برنامهنویسی شیئگرا در قالب مثالی فرضی در زبان برنامهنویسی PHP بپردازیم. به طور کلی، دیزاین پترن تمپلیت زیرشاخۀ الگوهای طراحی Behavioral است و استفاده از آن در شرایطی مفید واقع میشود که برخی فیچرهایی مشترک برای چند کلاس مد نظر داریم به طوری که پیادهسازی آنها در تکتک کلاسهای مذکور منجر به اصطلاحاً Duplication در سورسکد میشود اما با استفاده از این دیزان پترن میتوان ساختار کلی الگوریتم مد نظر و همچنین متدهای مشترک مابین کلاسهای مذکور را در تنها یک کلاس به اصطلاح Template پیادهسازی کرده و هر کلاس فرزندی که از آن ارثبری کند باید متدها و فیچرهای مد نظر متناسب با نیاز خود را بیفزاید. به عبارتی، یک اسکلت یا قالب اصلی وجود دارد که کلیهٔ سابکلاسها از آن قالب تبعیت کرده اما در عین حال هر کدام کدهای اختصاصی خود را دارند.
حال به منظور درک بهتر ساختار دیزاین پترن تمپلیت و پیادهسازی این الگوی طراحی مثالی را در نظر میگیریم که در آن قصد داریم تا کلاسی مجزا به منظور چاپ استرینگ مربوط به نام کتابی برای پرینت گرفتن از آن و کلاسی دیگر برای چاپ استرینگ مربوط به نام کتاب الکترونیکی مد نظر برای تهیۀ فایل پیدیاف از آن را پیادهسازی کنیم به طوری که هر دو کلاس مذکور ویژگیهای مشترکی همچون متدی برای چاپ نام مربوطه را از کلاس تمپلیت ارثبری خواهند کرد. برای این منظور، پوشهای تحت عنوان template-design-pattern
در لوکالهاست تعریف کرده و در ادامه فایلهای پروژۀ خود را بر اساس ساختار زیر ایجاد میکنیم:
template-design-pattern/
├── Book.php
├── Ebook.php
├── index.php
└── PaperBack.php
پیش از هر توضیحی، لازم به یادآوری است که تمامی فایلهای این آموزش با دستور php?>
شروع میشوند که به دلیل شلوغ نشدن کدها، از نوشتن آن در تمامی اسکریپتها خودداری کردهایم.
کلاس اَبسترکت چیست؟
Abstract Class زمانی استفاده میشود که بخواهیم دولوپرها را موظف سازیم تا در حین ارثبری حتماً متد خاصی را پیادهسازی کنند و این در حالی است که صرفاً در مورد نام متد اطمینان داریم و نمیدانیم الگوریتم داخلش به چه شکل باید باشد. زمانی که کلاسی از جنس اَبسترکت مینویسیم، موظف هستیم تا حداقل یک متد از جنس اَبسترکت نیز داخل آن کلاس تعریف نماییم و لازم به توضیح است که متدهای اَبسترکت فقط حاوی نام و احتمالاً آرگومانهای ورودی هستند که با این تفاسیر هرگز قادر به ساخت آبجکت از روی کلاسهای اَبسترکت نخواهیم بود بلکه برای ساخت یک آبجکت، ابتدا باید یک کلاس فرزند بسازیم که از کلاس اَبسترکت والد ارثبری کرده باشد سپس الگوریتم مد نظر خود را داخل کلاس فرزند پیادهسازی نماییم.
به نوعی میتوان کلاسهای اَبسترکت را به اینترفیسها تشبیه کرد با این تفاوت که اینترفیس یک کلاس اَبسترکت است که کلیهٔ متدهایش اَبسترکت میباشند اما این در حالی است که در کلاسهای اَبسترکت علاوه بر حداقل یک متد اَبسترکت، میتوان متدهای معمولی نیز داشت.
حال با در نظر گرفتن توضیحات فوق، در ابتدا کلاسی تحت عنوان Book
را در فایلی به نام Book.php
ساخته به طوری که حاوی فیچرها و فانکشنهای مشترک مابین کلاسهای PaperBack
و Ebook
است:
abstract class Book {
abstract public function generateName($name);
}
همانطور که مشاهده میکنید، با قرار دادن کلیدواژهٔ abstract
قبل از نام کلاس، کلاسی از نوع اَبسترکت تحت عنوان Book
ساختهایم تا در نقش یک قالب به اصطلاح Parent (والد) بوده که حاوی متدی است که مابین کلیهٔ کلاسهای Child (فرزند) مشترک خواهد بود. در ادامه فانکشنی از جسن اَبسترکت به نام ()generateName
با یک آرگومان ورودی تحت عنوان name$
پیادهسازی کردهایم که این وظیفه را دارا است تا نام کتاب را به عنوان پارامتر ورودی گرفته و آن را چاپ کند.
همانطور که پیش از این گفتیم که از روی کلاسهای اَبسترکت نمیتوان آبجکت ساخت، لذا نیاز است تا بسته به نیاز وب اپلیکیشن خود دست به ساخت یکسری کلاس فرزند بزنیم بدین صورت که برای متد اَبسترکتِ داخل کلاس اَبسترکتِ فوق Body (بدنه) تعریف شود که برای همین منظور در این مرحله متناسب با نیاز پروژۀ خود کلاسی تحت عنوان PaperBack
را داخل فایلی به نام PaperBack.php
و به منظور چاپ استرینگ مربوط به نام کتاب مد نظر برای پرینت گرفتن از آن پیادهسازی میکنیم که در همین راستا فایل مذکور را بدین صورت تکمیل میکنیم:
require_once 'Book.php';
class PaperBack extends Book {
public function generateName($name) {
echo "The Book Name Is \"$name\" & Should Be Printed.";
}
}
در کد فوق کلاسی به نام PaperBack
ساخته و آن را از کلاس Book
ارثبری کردهایم که بدین ترتیب به چارچوب کلی این کلاس دسترسی داشته و موظف هستیم تا برای فانکشن اَبسترکت ()generateName
منطقی خاص این کلاس تعریف کنیم که این منطق عبارت است از چاپ نام کتاب (پارامتر ورودی) داخل علائم دابلکوتیشن (در واقع، قرار دادن علامت /
قبل از "
منجر به این خواهد شد که این علامت توسط مفسر پیاچپی در خروجی چاپ شود.)
همچنین کلاسی دیگر تحت عنوان Ebook
را داخل فایلی به نام Ebook.php
و به منظور چاپ استرینگ مربوط به نام کتاب الکترونیکی مد نظر برای تهیۀ فایل پیدیاف از آن توسعه میدهیم که برای این منظور کدی مانند زیر خواهیم داشت:
require_once 'Book.php';
class Ebook extends Book {
public function generateName($name) {
echo "A PDF Was Generated for The eBook \"$name\".";
}
}
در کد فوق، ابتدا فایل مربوط به کلاس پَرنت را ایمپورت کرده و در ادامه کلاسی به نام Ebook
ساختهایم که از کلاس اَبسترکت Book
ارثبری میکند و در ادامه فانکشن اَبسترکت ()generateName
را تکمیل کردهایم بدین صورت که پارامتر ورودی مربوط به نام کتاب الکترونیکی مد نظر را داخل علائم " "
قرار داده و با استرینگ «.A PDF Was Generated for The eBook» کانکت کرده و در خروجی چاپ میکند.
حال برای تست اپلیکیشن، کدهای زیر را در فایل index.php
نوشته و آن را اجرا میکنیم:
require_once 'PaperBack.php';
$paperback = new PaperBack();
$paperback->generateName("Good to Great");
در کد فوق ابتدا فایل مربوطه را ایمپورت کرده و در ادامه آبجکتی تحت عنوان paperback$
از روی کلاس PaperBack
ساختهایم که در ادامه فانکشن ()generateName
را روی آبجکت ساختهشده فراخوانی میکنیم و استرینگ فوق را به عنوان پارامتر ورودی به آن میدهیم که در نهایت استرینگ زیر را در خروجی خواهیم داشت:
The Book Name Is "Good to Great" & Should Be Printed.
اکنون به منظور تست عملکرد کلاس Ebook
کدهای قبل را از فایل index.php
پاک کرده و کدهای زیر را در آن مینویسیم:
require_once 'Ebook.php';
$ebook = new Ebook();
$ebook->generateName("PHP & MySQL FOR Dummies");
عملکرد کلاس فوق نیز مشابه کلاس پیشین میباشد با این تفاوت که فراخوانی فانکشن ()generatePdf
از کلاس Ebook
در نهایت منجر به چاپ استرینگ زیر در خروجی خواهد شد:
A PDF Was Generated for The eBook "PHP & MySQL FOR Dummies".
همانطور که میبینید، پارامتر ورودی مربوط به نام کتاب الکترونیکی داخل علائم دابلکوتیشن با استرینگ مد نظر کانکت شده و در معرض دید ما قرار گرفته است.
جمعبندی
به طور کلی، دیزاین پترن تمپلیت سادهترین نوع از الگوهای طراحی بوده و به منظور کاهش کدهای مشابه در هر یک از کلاسهای اپلیکیشن و انتقال آنها به کلاس تمپلیت مورد استفاده قرار میگیرد به طوری که کلاسهای مذکور ویژگیهای مشابه را از آن ارثبری میکنند که این امر منجر به سادگی سورسکد میشود.