جاوا و تکنولوژی های آن

java programming language

در این وبلاگ به بررسی نکات موجود در جاوا و تکنولوژی های آن می پردازیم

طبقه بندی موضوعی

۲ مطلب با کلمه‌ی کلیدی «design pattern» ثبت شده است

Creational Design Patterns


singleton : از ابجکت تنها یکبار instance ساخته شود و هر باری که یک instance میگیریم به همان ابجکت اولیه اشاره کند

کاربرد : Logger , DB Connection , Caching , Thread Pool , ...


Factory : یک Interface یا Abstract class داشته باشیم و در runtime تصمیم بگیریم که کدام یک از فرزندان آنرا بسته به شرایط انتخاب و ایجاد کنیم

کاربرد : انعطاف پذیری Instance ایجاد شده و وابستگی کمتر به یک کلاس در شرایطی که یک کلاس چندین کاربرد را میتواند برای ما داشته باشد مثلا فرض کنید مالیات فروش در یک سال با سال دیگر فرق کند کافی است دو کلاس فرزند با ضریب مالیات مختلف ایجاد کنیم و بعد در کد استفاده کنیم


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

کاربرد : مواقعی که نیاز باشد چندین نوع Instance که مربوط به یک موضوع باشند را از طریق Factory انتخاب و ایجاد کنیم


Prototype : همانطور که از اسمش پیداست (نمونه اولیه) از Instance ساخته شده یک clone می دهد و دو نوع clone داریم یکی Shallow و دیگری Deep Copy که سطحی و عمیق هستند با اینترفیس Clonable و متد clone یک Shallow کپی داریم و با اینترفیس Serializable یک Deep Copy از ابجکت داریم

کاربرد : زمانی که میخواهیم یک ابجکت دیگر عین ابجکت جاری داشته باشیم ولی Reference آن یکی نباشد و کاملا مستقل باشد


Registery : یک دفتر ثبت ابجکت و یک کلید دارد که با دادن کلید یک clone از آن ابجکت میگیرد و برمیگرداند و با Prototype قابل ادغام است

کاربرد : زمانیکه نیاز داریم از یک ابجکت و محتوای درون آن تعداد زیادی استفاده کنیم


Builder : یکی از پر کاربردترین الگو های طراحی است و زمانی که بخواهیم پیچیدگی های ایجاد یک ابجکت بزرگ را ساختارمند کنیم میتوانیم استفاده کنیم

کاربرد : زمانی که یک ابجکت برای ایجاد شدن نیاز به کانفیگ ها و پارامتر های زیادی باشد ساخت آن ابجکت را ساده تر میکند نمونه این الگو را در اپلیکیشن سرور ها میتوان دید


Object Pool : زمانی که استفاده از یک نوع ابجکت بسیار زیاد ، ایجاد و یا دسترسی به آن ابجکت زمان بر و یا حجم زیادی را روی حافظه اشغال کند ما نیاز داریم که این نوع از ابجکت ها را بعد از ایجاد و استفاده از بین نبریم و باز دوباره آنها را مورد باز استفاده قرار دهیم برای این منظور نیاز به یک Container ای داریم که آن ابجکت ها را برای ما مدیریت کنند و مواقعی که نیاز داریم یکی به ما بدهد و مواقعی که در حال استفاده است آنرا به درخواست کننده دیگر ندهد و در پایان آن ابجکت را دوباره نگهداری کند

کاربرد : پرفرمانس کد را بسیار بالا میبرد و مصرف منابع سیستم را بسیار کمتر خواهد کرد و به ابجکت ها قابلیت استفاده مجدد را میدهد مثل DB Connection 




Structural Design Patterns


Adapter : موقعی که ابجکتی اولیه نیاز به ابجکتی ثانویه دیگری دارد و ما برای ایجاد آن ابجکت ثانویه باید اطلاعات یک یا چند ابجکت دیگر را که با ابجکت اولیه ناسازگار هستند را در قالب ابجکت ثانویه تبدیل کنیم تا مورد استفاده ابجکت اولیه قرار گیرد اینجا باید از الگوی adapter برای تبدیل استفاده کنیم و اطلاعات مورد نیاز را استخراج و به یک ابجکت جدید تبدیل کنیم

کاربرد : زمانی که ابجکت نا سازگار با آن چیزی که مورد استفاده است داشته باشیم و برای ایجاد باید اطلاعات مورد نظر را جهت هماهنگی تبدیل به ابجکتی دیگر کنیم


Bridge : فرض کنید یک توالی ارث بری شده از کلاس های Abstract یا interface ها داریم که در هر لایه دارای متد هایی برای انجام وظایفی وجود دارد و تعداد زیادی پیاده سازی از آنها برای شرایط مختلف مورد نیاز است (n در m حالت) که این خود حجم زیادی کدنویسی میبرد و همین تعداد زیاد کلاس های پیاده سازی شده شرایط استفاده را پیچیده و نگهداری و بازنویسی کد را هم ضعیف میکند ، کوچکترین تغییری در یکی از سلسله مراتب ارث بری منجر به بازنویسی در تعداد زیادی کلاس پیاده ساز خواهد شد و برنامه انعطاف پذیری پایینی خواهد داشت

تکنیک ساخت Bridge : در کد هایی که این وضعیت را دارند (تعداد زیادی کلاس Concrete برای حالت های مختلف کاری) می آییم نگاه میکنیم کدام قسمت ها را میتوان جدا کرد (interface یا abstract کلاس های موجود در سلسله ارث بری موجود هستند) ، این تکنیک جدا سازی باید متمرکز و محدود به انجام یک task واحد باشد و بعد حالت های مختلف فقط آن task را پیاده سازی میکنیم ، برای بقیه لایه های جدا شده هم پیاده سازی های مختلف را در نظر میگیریم

و بعد در کلاس نهایی که قرار است مورد استفاده قرار گیرد اینترفیس مربوطه را بصورت Composition وارد میکنیم و از طریق Constractor پیاده ساز مورد نظر را به آن ارسال میکنیم و بعد با متد های مورد نظرش کار کنیم به این تکنیک پل ساختن یا Bridge میگویند

کاربرد : منعطف کردن برنامه و کم کردن پیچیدگی های حاصل از ایجاد تعداد زیادی پیاده سازی برای حالت های مختلف کاری و اگر نیاز بود ویژگی جدید یا task جدیدی اضافه شود با کمترین زمان و پیچیدگی قابل اضافه شدن است


Composite :  به ترکیب یک نوع ابجکت درون ابجکت خودش هست (مثلا کارکنان یک سازمان) و با Composition فرق دارد و هر جا که ساختار درختی داشتیم میتوانیم از Composite استفاده کنیم و در این الگوی طراحی معمولا سه نوع ابجکت را خواهیم داشت : Component , Leaf , Composite 

component همان کلاس پدر اول است که همه از آن ارث بری کرده اند (در مورد لیست کارکنان یک سازمان می شود اینترفیس Employee)

Leaf کلاس هایی که فرزندان را تشکیل میدهند و ممکن است با هم یک فرق هایی هم داشته باشند

Composite همان ابجکت بزرگ است که در بر گیرنده root و تمامی leaf ها است و دارای رابطه یک به چند دارد چون هر node میتواند خود شامل تعداد زیادی sub-node باشد و همینطور ساختار درختی خواهیم داشت تا به آخرین node برسیم و معمولا داخل ابجکت composite متد های add , remove , getChild , operation داریم

کاربرد : ساختار ارث بری را آنجا که نیاز داریم ابجکت هایی از یک نوع زیر مجموعه خودشان قرار گیرند یکسان میکند


Decorator : نام دیگرش Wrapper است و هدف این الگوی طراحی اضافه کردن ویژگی های جدید به یک سلسله مراتب ارث بری که از قبل وجود دارد به این صورت که مثلا به متد (ویژگی) کنونی رفتاری جدیدتر و یا بیشتری را اعمال کنیم و رابطه کلاس های فرزند با پدرشان رابطه Composition است پس در طراحی نیاز به ارث بری و Composition داریم و نیاز به یک Constractor داریم که ابجکتی از جنس Hierarchy به عنوان آرگومان بگیرد و بعد و یا قبل و یا بجای اجرای متد خاص آن Composition Object ویژگی های خاص مورد نظر را اضافه کنیم مثل DataOutputStream

کاربرد : اضافه کردن یک رفتار جدید بدون تاثیر گذاری روی اصل پیاده سازی 


Facade : موقعی که ما یک API پیچیده داریم که شامل تعداد زیادی کلاس باشد که هر یک کاری را انجام میدهند برای ساده سازی کار با API نیاز به یک Facade داریم که ما یا آن کار کنیم و هر نوع سرویسی که میخواهیم را آن برای ما فراهم کند و به این صورت است که داخلش کلاس های سرویس Composition شده است و متد های آنها را مشابه سازی کرده و یا دارای یک متد است که وقتی صدا زده میشود از آن سرویس ها داخلیش استفاده میکند در واقع درخواست را به کلاس ها داخلی delegate میکند 

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

کاربرد : ساده سازی استفاده از سرویس های سیستم خصوصا سرویس هایی که مرتبط با یک حوزه کاری باشند


ّFlyweight : مواقعی که نیاز است ابجکت هایی داشته باشیم که خیلی پر کاربرد هستند و مرتب باید instance از آنها ساخته شود ، Immutable هستند مثل String 

معمولا یک Map با id و interface پدر اصلی ایجاد میکنیم و با دادن id ابجکت مورد نظر را دریافت میکنیم و اگر آن ابجکت نبود یکی ایجاد میشود 

اینطوری ابجکت ها بعد از استفاده از بین نمی روند و در cache ما وجود خواهند داشت

اگر بخواهیم ابجکت ها هر یک scope مختص به خود را داشته باشند هنگام گرفتن ابجکت یک clone از آن میگیریم و بعد بر می گردانیم

کاربرد : بهینه سازی مصرف حافظه با مدیریت بهتر ابجکت ها تا مقدار کمتری حافظه را اشغال کند


Strategy : در این الگوی طراحی میخواهیم بتوانیم بصورت داینامیک رفتار یک کلاس را نسبت به شرایط تغییر دهیم ، اینکار باعث میشه از عبارات شرطی برای تعیین رفتار در شرایط مختلف استفاده نکنیم ، اینطوری یک کلاس abstract یا interface میگیریم و بعد رفتار های مختلف را پیاده و در شرایط مختلف از پیاده سازی های مختلف نسبت به استراتژی تعیین شده استفاده میکنیم 

در جاوا 8 اساس لامبدا بر اساس همین الگوی طراحی میباشد

نحوه استفاده : استراتژی پیاده شده را در runtime به کلاس اصلی composition میکنیم و بعد از ان استفاده میکنیم 

کاربرد : استفاده از حالت های رفتاری مختلف از پیش تعیین شده طبق استراتژی مورد نظر


Proxy : خیلی شبیه Decorator و گاهی شبیه Adapter است و تنها هدفش با آن فرق دارد . همانند Decorator امکان Wrapping را میدهد . به این صورت است که یک interface داریم که پیاده سازی هایی دارد و از آن ابجکتی که نیاز داریم یک ابجکت Composition میکند و به ابجکت اصلیمون functionality اضافه میکند

در طراحی نیاز داریم یک interface اصلی داشته باشیم که آن interface پیاده سازی هایی دارد (Real Object) و ابجکت Proxy مون هم از این Interface پیاده سازی کرده و داخل proxy یک ابجکت از نوع real object ها بصورت composition خواهیم داشت و وقتی client بخواهد با متد های proxy کار کند (دقت کنید که proxy خودش از نوع interface پدر است) ابجکت proxy متد های real object را call خواهد کرد با این تفاوت که متواند قبل از اجرا و بعد از اجرا یکسری عملیات اضافه ای داشته باشیم

تفاوت Proxy و Decorator : 

در Proxy همانند decorator میتواند روی real object یکسری قابلیت اجرا اضافه کند ولی هدف Proxy از اینکار کنترل real object است و نه عوض کردن نحوه اجرا عملیات مثل پیاد سازی امنیت اجرای عملیات و یا انجام caching و یا lazy objects

در proxy در compile time مشخص است که real object از چه نوعی است ولی در decorator اینطور نیست

کاربرد : کنترل ابجکت هدف مثل پیاده سازی سیستم Logging قبل و بعد از اجرای عملیات که در گیر پیاده سازی نشویم پیاده سازی لایه امنیت ، ساده سازی پیاده سازی عملیات ، RMI ، DI IOC استفاده میشود که از لحاظ ساختاری به الگوهای Decorator و Adapter شباهت هایی دارد


AOP در واقع با proxy کار میکند 

در جاوا رسما این الگوی طراحی پیاده سازی شده است و در java.lang.reflect.Proxy  موجود است و به آن JDK Proxy میگویند که مکانیزمی دارد که اجازه میدهد ما proxy ها را راحت تر پیاده سازی بکنیم و برای استفاده متوانیم به این صورت اقدام کنیم :


public interface Proxy_IService {

    public void serviceCalling();
}


public class Proxy_ServiceRealObjectImpl implements Proxy_IService{

    @Override
    public void serviceCalling() {
        System.out.println(getClass().getSimpleName()+ " service called!");
    }
    
}


import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class Proxy_ServiceProxyObjectImpl implements InvocationHandler {

    Proxy_IService proxyRealObject;

    public Proxy_ServiceProxyObjectImpl(Proxy_IService proxyRealObject) {
        this.proxyRealObject = proxyRealObject;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println(getClass().getSimpleName() + " service invoked!");
        Object invocation = method.invoke(proxyRealObject, args);
        System.out.println(getClass().getSimpleName() + " END service invoked!");
        return invocation;
    }

    //static proxy service creator
    public static Proxy_IService createProxyService(Proxy_IService proxy_IService) {
        Proxy_IService proxyRealObject = (Proxy_IService) Proxy.newProxyInstance(proxy_IService.getClass().getClassLoader(), proxy_IService.getClass().getInterfaces(),
                new Proxy_ServiceProxyObjectImpl(proxy_IService));
        return proxyRealObject;
    }

}


public class TestProxy {

    private static Proxy_IService proxy_IService;

    public static void main(String[] args) {
        proxy_IService = new Proxy_ServiceRealObjectImpl();
        Proxy_IService proxy_IService2 = Proxy_ServiceProxyObjectImpl.createProxyService(proxy_IService);
        proxy_IService2.serviceCalling();
    }

}


output :
Proxy_ServiceProxyObjectImpl service invoked!
Proxy_ServiceRealObjectImpl service called!
Proxy_ServiceProxyObjectImpl END service invoked!



Behavioral Design Pattern


Chain of Responsibility : به معنی زنجیره مسولیت ها ، موقعی پیش میاد که برای اجرای یکسری از عملیات یکسری Handler داریم که میخواهیم سلسله عملیات ما را انجام دهند به هر یک از این handler ها یک حلقه زنجیره گفته میشود و اینطوری کار میکند که هر حلقه زنجیره که کارش تمام شد ادامه کار به زنجیره بعدی ارسال میشود 

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

کاربرد : میتوانیم بصورت داینامیک زنجیره ها را کم و زیاد کنیم و یا پیاده سازی های مختلفی را برای یک نوع از کار تعریف کنیم loosely couple می شود 


Command : این الگو یکسری دستورالعمل را به ابجکتی که آن دستورات را دریافت میکند و اجرا میکند ایجاد میکند و برای طراحی به یک Command Interface و ابجکت هایی به ازای هر دستور و پیاده سازی متد های دستورات و Invoker و Reciever 

کاربرد : تعیین دستورات اجرایی طبق ساختار از پیش تعیین شده به ابجکت هایی که آن رفتار را بپذیرند و درخواست کننده دستورات را از اجرا کننده دستورات جدا میکند و اینطوری انعطاف پذیری بیشتری خواهیم داشت


Interpreter : برای ایجاد ساختاری گرامری در برنامه میتوان از این الگوی طراحی استفاده کرد مانند Regular Expression ها که یک رشته را به عنوان ورودی از کاربر میگیرد و انرا تبدیل به یک کد قابل اجرا میکند در واقع آن رشته یک ساختار معنا داری دارد که میتوان آنرا به کد اجرایی تفسیر کرد و در طراحی این الگو چند نوع ابجکت درگیر هستند :

َ- AbstractExpression : ابجکتی است که کلیه sub-abstration ها داخلش پیاده سازی شده که در موقع اجرا مورد استفاده قرار میگیرند

- TerminalExpression : کلاسی است که عملیات تفسیر کردن از آن آغاز میشود و sub-class ای از AbstractExpression است 

- NonterminalExpression : یکسری ترمینال هستند که داخل هم compose میشوند و sub-class ای از AbstractExpression است 

- Context : چیزی است که مورد تفسیر قرار میگیرد همان رشته ورودی که درخواست کننده ارسال میکند

- Client : درخواست کننده تفسیر

کاربرد : میتوانیم یک ساختار تفسیری دلخواه و گرامری برای انجام عملیاتی که در آینده قرار است ابتدا تفسیر شود و بعد عملیاتی را انجام دهد ، ایجاد کنیم


Iterator : از این الگوی طراحی برای انجام پیمایش استفاده میشود و پیچیدگی های نحوه پیمایش از استفاده کننده مخفی است و اینطوری میتوانیم الگوریتم پیمایش را از منطق برنامه جدا کنیم و برای پیاده سازی :

 یک اینترفیس میخواهیم که متد های hasNext و next داخلش باشد بنام Iterator مثلا

یک متد factory داخل container نیاز داریم که از طریق آن بتوانیم یک Iterator پیاده سازی و تولید کنیم و در اجرا به اینترفیس منسوب کنیم

در جاوا نیازی نیست ما تمام مراحل را پیاده سازی کنیم برای اینکه ابجکتی از نوع Iterator داشته باشیم کافی است از اینترفیس Iterable پیاده سازی کنیم 

کاربرد : ایجاد پیمایش روی ساختار sequential 


Mediator : یک کلاس واسط است که بین چندین کلاس قرار میگیرد و هدف این است که ابجکت های دیگر براحتی بتوانند با این ابجکت واسط ارتباط برقرار بکنند ، امکان استفاده دوباره از ابجکت ها وجود دارد و Mediator یک جور نقش Router و Hub را در برنامه بازی میکند

کاربرد : زمانی که در برنامه ارتباط بین ابجکت ها زیاد باشد برای هماهنگی و نقش واسط میتوان به این الگو فکر کرد


Memento : با این الگو میتوان state ابجکت ها را نگه داری کرد که بعدا به آن state برگردیم و برای طراحی سه نوع کلاس داریم :

- Originator : همان ابجکت اصلی که میخواهیم state فعلی آن را نگه داریم

- Memento : ابجکت کپی است که از روی Originator برمیداریم و ممکن است در لحظه استفاده با Originator یکسان باشد 

- Caretaker : مسول نگه داری و پیاده ساز Memento ها است 

بهتر است برای نگه داری ابجکت ها برای طولانی مدت از فایل استفاده کنیم و از ObjectInputStream و ObjectOutputStream استفاده کنیم و برای کوتاه مدت از کلاس Stack یا LinkedList استفاده کنیم که در حافظه رم ذخیره خواهد شد ، استفاده از Serializable و clone توصیه نمیشود چون وجود Constractor را از دست میدهیم و برنامه buggy میشود چون یکسری از rule ها و logic ها را از دست خواهیم داد 

کاربرد : گذاشتن یک save point در برنامه که در حالت های مختلف بخواهیم به آن حالت برگردیم


Observer : در این طراحی یک Subject داریم و یکسری دنبال کننده Subject که تغییرات Subject را رصد میکنند و وقتی اتفاقی در Subject افتاد همه دنبال کننده ها باخبر میشوند 

در جاوا یک کلاس برای طراحی راحت تر این الگو داریم که در java.util.Observer قرار دارد و برای پیاده سازی کافی است ابجکت subject از java.util.Observable ارث بری کند این کلاس همان کلاسی است که بقیه کلاس ها تغییرات آنرا قرار است دنبال کنند

و درون کلاس subject یک متدی مینویسیم و آرگومانی که قرار است به دنبال کننده ها ارسال شود را هم مینویسیم که در ابتدای بدنه این متد ، از کلاس Observable متد setCahnged را فراخوانی میکنیم که به همه دنبال کننده ها خبر میدهد که تغییری رخ داده است و با متد notifyObservers آن ابجکت ورودی را به همه دنبال کننده ها ارسال میکنیم 

برای دنبال کننده ها کافی است از اینترفیس java.util.Observer ارث بری و متد update را پیاده سازی میکنیم

و بعد برای اجرا وقتی از کلاس subject یک instance میسازیم که خود این کلاس Observable هم هست و با متد addObserver دنبال کننده ها را به آن اضافه میکنیم

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


State : به مقادیری که به ازای هر ابجکتی درون آن وجود دارد (فیلد ها) و میخواهیم وضعیت های خاصی از ابجکت ها را نگه داری کنیم 

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

و یک اینترفیس State داریم که پیاده سازی های مختلفی خواهد داشت

کاربرد : نگه داری state های مختلف کاری و تغییر دادن state در حالت های مختلفی که میخواهیم داشته باشیم مانند ریموت کنترل تلویزیون 


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

طراحی : یک کلاس abstract میگیریم و متد های مشترک را پیاده سازی میکنیم و متد یا متد هایی که مشترکا وجود دارند و استفاده میشوند ولی قرار است نسبت به شرایط فرق داشته باشد را از نوع abstract میگیریم و کلاس های دیگر که از این کلاس ارث بری کنند آن متد ها را پیاده سازی میکنند به ایجاد کلاس پایه که رفتار های مشترک را پوشش داده و رفتار های مختلف را اماده پیاده سازی کرده است یک Template pattern میگویند 

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


Visitor : موقعی که نیاز است functionality کد را به یک ابجکت دیگر بسپاریم که ان یکسری تغییرات را در کد ما انجام میدهند و به ما برمیگرداند 

یک عنصر element داریم که قرار است Visitor روی آن تاثیر بگذارد و یک Visitor داریم که کارش اعمال تغییرات است 

طراحی : یک کلاس client داریم 

در جاوا کلاس های کمکی برای پیاده سازی این الگوی طراحی موجود است :

 java.lang.model.element.Element  و  java.lang.model.element.ElementVisitor 

کاربرد : میتوانیم یک کلاس پایه داشته باشیم و تغییرات آنرا بیرون از کلاس پیاده سازی کنیم و یا یک adapting ایجاد بکنیم ، در این صورت پیچیدگی های کد کمتر خواهد شد




دیزاین پترن ها الگو ها و تفکر کدنویسی استاندارد و تکرار پذیری هستند که طی سالها چالش هایی که متخصصان در حین تولید نرم افزار به آن بر خورده اند به تکامل رسیده اند


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


پیروی از الگو های دیزاین پترن ها کمک میکند که قابلیت نگهداری ،بازنگری ، کیفیت و ساختار کدنویسی بهتری داشته باشیم


گاهی در حین تولید نرم افزار نیاز به الگو هایی برای نحوه تولید ابجکت ها نیاز داریم که به آن Creational Design Pattern میگوند حال ممکن است فکر کنید که همیشه میتوان یک ابجکت را با new کردن یک instance از آن ساخت و چه نیازی به یک الگو دارد ؟

خیلی از اوغات ما میخواهیم هویت یک ابجکت را به طور دیگری پیاده سازی کنیم و اینقدر برنامه درگیر پیچیدگی هایی میشود که نیاز دارد یک استانداردی برای اینکار داشته باشیم


گاهی در حین تولید نرم افزار نیاز به الگو هایی برای ساختار درونی و ترکیب ابجکت ها نیاز داریم که به آن Structural Design Pattern میگوند

این دسته از دیزاین پترن ها به چگونگی ارتباط بین ابجکت ها برای ترکیب شدن باهم میپردازد 


گاهی در حین تولید نرم افزار نیاز به الگو هایی برای نحوه رفتار ابجکت ها و جدا کردن عملیات درونی نیاز داریم که به آن Behavioral Design Pattern میگوند

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


نکته مهمی که وجود دارد این است که بسته به زبان و تکنولوژی مورد استفاده بعضی از این دیزاین پترن ها کاربردی ندارد و مسایلی که الگوهای طراحی حل میکنند در زبان و تکنولوژی حل شده اند مانند وقتی که از AOP استفاده میکنید و یا زبان هایی که در درونشان مشکلات را حل کرده اند 

پس درک عمیق از آنچه که نیاز دارید و انچه که مشکل شما را حل میکند بسیار مهم است و گاها دولوپر هایی با سالها سابقه اشتباهات تکنیکی این چنینی میکنند و محتمل است