پارسا کاویان پور
پارسا کاویان پور
خواندن ۲ دقیقه·۲ سال پیش

Static Factory Method

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


1- سازنده ها یک نام با معنی ندارند. با استفاده از Static factory method میتونید یک نام با معنی استفاده کنید.


2-سازنده ها نمیتونن چیزی Return کنن.ولی Static factory method میتونه Return داشته باشه. پس در این مورد هم انعطاف پذیری بیشتری داریم


3- میتونیم باهاش ساخته شدن شی ء رو محدود کنیم درحالی که در سازنده حتما شی جدید ساخته میشه. این بهمون قدرت استفاده از مکانیزم های Caching رو میده(مثل متد Integer.valueOf که درواقع از بازه ی -128 تا +127 رو کش شده داره و اگر در این بازه بهش عدد بدید یک شیء جدید از Integer نمیسازه). یکی از عینی ترین نمود هاش الگوری Singleton هست که درواقع داخلش ما از Static factory method استفاده میکنیم(همون متد getInstance که همه داخل سینگلتون دیدیمش).


  • 4-بعضی حرکت هارو نمیشه داخل سازنده زد مثلا مقدار دهی متغیر های نمونه استاتیک. در چنین حالتی باید از static block استفاده کنیم که به محض Load شدن کلاس در حافظه اجرا میشه. ولی با Static factory method میتونیم به صورت Lazy initialization این فیلد هارو مقدار دهی کنیم.

دقیقا کجاها استفاده شده؟ چند مثال :


1-متد valueOf در کلاس String و Integer و...

2-متد های Of,ofNullable,empty کلاس Optional .

3-تمام متد های کلاس Collections. که هیچ جوره نمیشه ازش شیء ساخت.


حالا تعریفش چطوریه؟؟


اول فرض کنید که یک کلاس User داریم و میخوایم هرموقع شیء جدیدی ایجاد شد زمانش رو لاگ کنیم.ایا درسته که در سازنده کد لاگ کردن رو بنویسیم؟ در این صورت اصل Single Responsibility Principle(SRP) رو نقض کردیم. این اصل به صورت ساده و مختصر بیان میکنه که هر متد یا هر کلاس قراره فقط یک وظیفه ی خاص رو انجام بده و این یعنی وقتی سازنده قراره مقدار دهی اولیه کنه نباید لاگ بندازه!!!

پس برای رعایت این اصل میایم از Static factory method استفاده میکنیم:


public class User { private static final LoggerLOGGER =Logger.getLogger(User .class. private final String name; private final String email; private final String country; public User(String name, String email, String country) { this.name = name; this.email = email; this.country = country; } // getters public static User createWithLoggedInstantiationTime(String name, String email, String country) { LOGGER.log(Level.INFO, &quotCreating User instance at : {0}&quot, LocalTime.now()); return new User(name, email, country); } }


البته بر حسب نیاز میتونید سازنده رو private یا public تعریف کنید.

امیدوارم به دردتون خورده باشه... موفق باشید!



منبع : Effective java



شاید از این پست‌ها خوشتان بیاید