مجموعه Java Effective قسمت 1

توی این سری میخوایم خلاصه‌ای از کتاب Java effective تالیف Joshua Bloch رو با هم به صورت خلاصه‌وار بررسی و مرور کنیم. این سری میتونه برای توسعه‌دهنده‌های اندروید خیلی مفید و کاربردی باشه. البته این نکته رو هم در نظر داشته باشید که لازمه‌ی مطالعه‌ی این قسمت‌ها آشنایی متوسط به بالا با جاوا هست. مولف این کتاب، این کتاب رو به قسمت‌هایی به نام تحت عنوان آیتم تقسیم کرده و شامل 57 آیتم هستش.

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

همیشه در نظر داشته باشید که به جای ایجاد constructorها میشه از static factory methods استفاده کنید. خب سوال پیش میاد منظور چیه؟

فرض کنید که میخواید یک instance از یک کلاس رو ایجاد کنید، این کار رو چطوری انجام میدید؟ احتمال زیاد از constructorها کمک میگیرید.

ولی موقعی که بخواید از static factory methods استفاده کنید چون از بیرون دسترسی مستقیم به این متد دارین، نیازی نیست که instanceای رو بسازید، دقت کنید به طور کلی کاری که factotyها انجام میدن ساخت آبجکت هست، این static factory method هم یک آبجکت از کلاس رو برای ما میسازه، یک مثال پیش پا افتاده و رایج از این چیزی که گفتیم توی اندروید، رو میشه ساخت Toast مثال زد - که البته با اومدن Snackbarها ممکنه به فراموشی سپرده بشن - مثل پایینی :

https://gist.github.com/sajjadyousefnia/9939307f602763294e92b3602325ac59

مثال مشابه و بهتری که میشه زد ، کلاس Object.animator هست که سه تا static factory method به نامهای ()ofArgb و ()ofInt و ()ofFloat داره، خب بگذریم static factory methods هم میتونن به جای constructorها استفاده بشن و هم میتونن علاوه بر constructorها استفاده بشن. و توی toast هم علاوه بر کانسترکتورها از static factory methods استفاده شده. من خودم به شخصه طرفدار استفاده از هر دو روش نیستم، چون باعث سردرگمی کسی که داره از کلاس ما استفاده میکنه میشه و مردد میمونه که از کدوم یکی استفاده کنه. پس بهتره که فقط از یکیشون استفاده کنیم و نه هر دو. البته گاهی اوقات لازم میشه که کانسترکتور رو public کنیم. ولی توی ObjectAnimator فقط میشه از static factory methods استفاده کرد. اگه خودتون نگاهی به سورس کد ObjectAnimator بندازید بهتر متوجه خواهید شد.

استفاده از static factory methods به جای Constructors چه مزایایی داره؟

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

مشکل بعدی‌ای که استفاده از کانسترکتورها داره اینه که هر کلاس به ازای هر نوع امضای خاص فقط میتونه یک دونه کانسترکتور داشته باشه، خیلی از توسعه‌دهنده‌ها سعی میکنن تا این مشکل رو با شیفت دادن جای پارامترها و عوض کردن جاشون با هم، حل کنن. که اصلا کار جالبی نیست و انجام این کار رو به هیچ وجه توصیه نمیکنیم. البته دلیل بد بودن این کار رو بعدا با هم بررسی میکنیم. در هر صورت هروقت خواستین که بیشتر از یک کانسترکتور با امضای یکسان رو توی یک کلاس بسازین 100درصد استفاده از static factory methods رو به شما پیشنهاد میکنیم.

مزیت دیگه‌ای که استفاده از static factory methods نسبت به کانسترکتورها داره اینه که، مثل حالت معمول، هر بار، موقع invoke کردن، مجبور نیستید که یک آبجکت جدیدی رو بسازید. اینجوری میتونید علاوه بر کانسترکتورها، instanceها رو هم cache کنید. منظورم اینه که فرض کنید ساختن یک آبجکت از یک کلاس برامون دشواری داشته باشه و مثلا حافظه‌ی زیادی رو بگیره، با این کاری که گفتم میتونیم تنها یک آبجکت از یک کلاس بسازیم و هر وقت که لازم بود returnاش کنیم. این کار فوق العاده میتونه مفید باشه. مخصوصا وقتی که در حال توسعه‌ی یک برنامه‌ی اندرویدی هستیم و منابع یا حافظه‌ی محدودی در اختیار ما هست، - که در اون صورت برای شما خیلی مهمه که یک آبجکت رو به چه بهایی میسازید -.

محدودیت بعدی‌ای که در مورد کانسترکتورها وجود داره و static factory methods برای ما حلش کرده، اینه که اینجوری میتونیم کلاسهای immutableای رو ایجاد کنیم، - البته در مورد مفهوم immutable نگران نباشید، بعدا در موردش بیشتر صحبت می‌کنیم. فعلا اینجوری در نظر بگیرید که کلاسهای immutable کلاسهایی هستن که وقتی ایجادشون کردیم دیگه نمیتونیم مقادیرشون رو تغییر بدیم - و این مساله به کاهش پیچیدگی دیزاین خیلی کمک میکنه. ولی کانسترکتورها همچین قابلیتی ندارن چون وقتی داریم ازشون استفاده میکنیم به ناچار یک آبجکت جدیدی رو ایجاد میکنیم ولی همچین اتفاقی توی static factory methods اتفاق نمیفته، همونطور که گفتم با static factory methods ه instanceهایی کاملا کنترل شده رو میشه تولید کرد و یک آبجکت رو چندین جا مورد استفاده قرار داد.

باید بگم که استفاده از static factory methods چندین مساله رو برای کلاس ما تضمین میکنه یکیش اینه که برای ما تضمین میکنه که این آبجکت ساخته شده یک singleton هست چون کلا یک آبجکت ساخته میشه که همون همه‌جا استفاده میشه و گاهی نیاز داریم که این آبجکت ساخته شده به صورت سینگلتون باشه، که به زودی توی قسمت سوم در موردش صحبت می‌کنیم. مساله‌ی بعدی اینه که چیزی که static factory methods برای ما تضمین میکنه اینه که آبجکت قابلیت instance سازی رو ندارن، به این معنی که اگه شما بخواید تعداد instanceهایی که از یک آبجکت ساخته میشه رو محدود کنید، و افراد دیگه بتونن تنها یک تعداد محدود و کنترل‌شده‌ای instance بسازن.

مزیت مهم دیگه‌ای که استفاده از factory static methods داره اینه که شما می‌تونید یک با استفاده از static factory methods میتونید نوع return رو به نوع دلخواهتون تغییر بدید،‌مثلا یک موقع بخواید یک آبجکتی رو return کنید که subtype اون کلاس باشه. ولی در مورد کانسترکتورها این موضوع فرق داره و توی نوع آبجکت return شده دستمون باز نیست و حتما باید از نوع همون کلاس باشه. ولی همونطور که گفتم این موضوع توی static factory methods وجود نداره و این متد میتونه مثل هر متد دیگه هر نوع آبجکتی رو return کنه. و این موضوع رو توی فریمورک کالکشن‌ها میتونیم ببینیم، چون هم میشه یک لیست و هم یک کالکشنی رو return کرد.

خب تا حالا در مورد مزایای استفاده از static factory methods صحبت کردیم، حالا میریم سراغ معایبش.

بزرگترین مشکل و عیبش اینه که اگه یک کلاسی کانسترکتور public یا protected نداشته باشه، نمیتونیم از روی اون subclassای ایجاد کنیم. بنابراین اگه نیاز به subclassای داشته باشیم نمیتونیم کانسترکتور رو private کنیم و همونطور که گفتم باید حداقل یک کانسترکتور private یا protected داشته باشیم.

خب مشکل بعدی استفاده از static factory methods اینه که توی حالت عادی نمیشه تشخیص داد که با یک static factory method روبرو هستیم یا یک متد معمولی چون برخلاف کانسترکتورها که مثلا از واژه‌ی new استفاده میکنن، توی static factory methods وجه تمایز خاصی - به جز اسمشون - نداریم. بعضی اوقات نام‌گذاری ممکنه مشکل بشه و ما نتونیم به کسی از کلاس ما استفاده میکنه تفهیم کنیم که از کدوم static factory method باید استفاده کنه و طرف گیج بشه، بنابراین باید از روش درستی برای نام‌گذاری اونا استفاده کنیم. نویسنده‌ی این کتاب گفته که استفاده از static factory methods رو در نظر داشته باشید و نه همیشه ازش به جای کانسترکتور استفاده کنید. بنابراین باید این اطمینان رو بدست بیاریم که جای صحیحی داریم از اون استفاده می‌کنیم.

خب کاربردش توی جاهایی که استفاده میشه رو بررسی می‌کنیم. از static factory methods میشه توی متد newInstance توی فرگمنت‌ها استفاده کرد. و امروزه هم زیاد هم از این روش استفاده میشه. به این متد که یک instance از کلاس فرگمنت رو return میکنه، میشه آرگومان Bundle رو هم اضافه کرد و ...

مثال دیگه‌ای که از کاربرد static factory methods میشه زد اینه : اگه بخوایم یک اکتیویتی یکسانی رو از چند جا شروع کنیم کارمون خیلی سخت میشه و نیاز به زدن کدهای خیلی زیادی داریم، ولی این مشکل رو میشه با استفاده از static factory methods حل کرد و یک راه حل خیلی خوب برای این کار ایجاد یک static factory method توی اکتیویتی و استفاده از اون برای هر وقت که خواستیم اکتیویتی رو شروع کنیم هست، داخل اون static factory method یک intent رو new می‌کنیم و هر وقت که لازم شد از این متد استفاده می‌کنیم و داخل همون متد Bundle مورد نیاز رو هم می‌فرستیم.

تلگرام : AndroidSenior@