نکات کلیدی
1. کارخانههای استاتیک به جای سازندهها: نامگذاری، کنترل و انعطافپذیری
ارائه یک روش کارخانه استاتیک به جای یک سازنده عمومی دارای مزایا و معایبی است.
مزایای نامگذاری. روشهای کارخانه استاتیک نامهای توصیفی ارائه میدهند، بر خلاف سازندهها، که به خوانایی و قابلیت استفاده از کد کمک میکند. این موضوع بهویژه زمانی مفید است که پارامترهای سازنده بهوضوح شیء ایجاد شده را نشان ندهند. بهعنوان مثال، یک روش به نام BigInteger.probablePrime()
توصیفیتر از یک سازنده BigInteger(int, int, Random)
است.
کنترل نمونه. کارخانههای استاتیک ملزم به ایجاد اشیاء جدید در هر بار فراخوانی نیستند، که به کلاسهای غیرقابل تغییر اجازه میدهد تا نمونهها را کش کرده و از ایجاد غیرضروری اشیاء جلوگیری کنند. این میتواند بهطور قابلتوجهی عملکرد را بهبود بخشد، بهویژه برای اشیاءی که بهطور مکرر درخواست میشوند. روش Boolean.valueOf(boolean)
نمونهای از این موضوع است، زیرا همیشه همان نمونههای Boolean.TRUE
یا Boolean.FALSE
را برمیگرداند.
انعطافپذیری زیرنوع. کارخانههای استاتیک میتوانند اشیاءی از هر زیرنوع نوع بازگشتی خود را برگردانند، که به APIها اجازه میدهد اشیاء را بدون عمومی کردن کلاسهایشان برگردانند. این موضوع API را فشردهتر کرده و اجازه میدهد کلاس بازگشتی بر اساس پارامترهای ورودی یا حتی در نسخههای مختلف تغییر کند، که به نگهداری و انعطافپذیری کمک میکند. این اساس چارچوبهای ارائهدهنده خدمات مانند Java Cryptography Extension (JCE) است.
2. پیادهسازی Singleton: سازندههای خصوصی و دسترسی عمومی
یک singleton به سادگی کلاسی است که دقیقاً یک بار نمونهسازی میشود [Gamma98، ص. 127].
تضمین یکتایی. Singletonها که نمایانگر اجزای منحصر به فرد سیستم هستند، با خصوصی کردن سازنده و ارائه یک عضو استاتیک عمومی برای دسترسی، تحمیل میشوند. این موضوع تضمین میکند که تنها یک نمونه وجود دارد. دو رویکرد رایج وجود دارد: استفاده از یک فیلد نهایی یا یک روش کارخانه استاتیک.
رویکرد فیلد نهایی. عضو استاتیک عمومی یک فیلد نهایی است که با نمونه singleton مقداردهی اولیه میشود. این رویکرد ساده است و مشخص میکند که کلاس یک singleton است. بهعنوان مثال:
public static final Elvis INSTANCE = new Elvis();
رویکرد کارخانه استاتیک. یک روش کارخانه استاتیک عمومی نمونه singleton را برمیگرداند. این موضوع انعطافپذیری را برای تغییر پیادهسازی بدون تغییر API فراهم میکند. بهعنوان مثال:
public static Elvis getInstance() { return INSTANCE; }
ملاحظات سریالسازی. برای حفظ ویژگی singleton در حین سریالسازی، باید یک روش readResolve
ارائه شود تا نمونه موجود را برگرداند و از ایجاد نمونههای جدید در هنگام دسرالیزه کردن جلوگیری کند. این موضوع تضمین میکند که singleton حتی پس از سریالسازی و دسرالیزه کردن نیز منحصر به فرد باقی بماند.
3. کلاسهای کاربردی: تحمیل عدم قابلیت نمونهسازی
چنین کلاسهای کاربردی برای نمونهسازی طراحی نشدهاند: یک نمونه بیمعنا خواهد بود.
هدف کلاسهای کاربردی. کلاسهای کاربردی که متدها و فیلدهای استاتیک را گروهبندی میکنند، برای سازماندهی عملکردهای مرتبط بر روی مقادیر اولیه، آرایهها یا اشیاءی که رابطهای خاصی را پیادهسازی میکنند، خدمت میکنند. آنها برای نمونهسازی طراحی نشدهاند، زیرا نمونهها بیمعنا خواهند بود. نمونههایی از این کلاسها شامل java.lang.Math
و java.util.Arrays
هستند.
جلوگیری از نمونهسازی. برای تحمیل عدم قابلیت نمونهسازی، یک ایدئوم ساده شامل گنجاندن یک سازنده خصوصی صریح است. این موضوع از تولید یک سازنده پیشفرض عمومی و بدون پارامتر توسط کامپایلر جلوگیری میکند و تضمین میکند که کلاس نمیتواند از خارج نمونهسازی شود.
عوارض جانبی. این ایدئوم همچنین از زیرکلاسسازی جلوگیری میکند، زیرا زیرکلاسها سازندهای برای فراخوانی سازنده سوپرکلاس نخواهند داشت. بهتر است یک توضیح در مورد هدف سازنده خصوصی گنجانده شود، زیرا ممکن است بهنظر غیرمعقول بیاید.
4. استفاده مجدد از اشیاء: کارایی و عدم تغییرپذیری
اغلب مناسب است که به جای ایجاد یک شیء جدید معادل عملکردی، از یک شیء واحد استفاده مجدد شود.
مزایای استفاده مجدد. استفاده مجدد از اشیاء، بهویژه اشیاء غیرقابل تغییر، کارآمدتر و شیکتر از ایجاد مکرر آنها است. زیرا ایجاد اشیاء و جمعآوری زباله میتواند پرهزینه باشد، بهویژه برای اشیاء سنگین. بهعنوان مثال، استفاده از String s = "silly";
بهتر از String s = new String("silly");
است.
اشیاء غیرقابل تغییر. اشیاء غیرقابل تغییر همیشه میتوانند بهطور ایمن استفاده مجدد شوند. بهعنوان مثال، Boolean.valueOf(String)
به Boolean(String)
ترجیح داده میشود زیرا اولی ممکن است از نمونههای موجود استفاده مجدد کند.
اشیاء قابل تغییر. اشیاء قابل تغییر میتوانند در صورتی که مشخص باشد تغییر نخواهند کرد، استفاده مجدد شوند. بهعنوان مثال، استفاده از مقداردهی استاتیک برای ایجاد نمونههای Calendar
و Date
یک بار، به جای ایجاد آنها هر بار که یک روش فراخوانی میشود، میتواند بهطور قابلتوجهی عملکرد را بهبود بخشد.
5. مدیریت حافظه: حذف ارجاعات منسوخ
یک ارجاع منسوخ به سادگی ارجاعی است که هرگز دوباره ارجاع نخواهد شد.
نشت حافظه. نشت حافظه در زبانهای جمعآوری زباله زمانی رخ میدهد که ارجاعات به اشیاء بهطور غیرعمدی نگهداری شوند و از جمعآوری زباله جلوگیری کنند. این موضوع میتواند منجر به کاهش عملکرد، افزایش حجم حافظه و حتی OutOfMemoryError
شود.
شناسایی نشت حافظه. یک منبع رایج نشت حافظه، کلاسهایی هستند که حافظه خود را مدیریت میکنند، مانند یک کلاس Stack
. زمانی که یک عنصر آزاد میشود، هر ارجاع شیء موجود در عنصر باید به null تغییر یابد.
راهحلها. برای جلوگیری از نشت حافظه، ارجاعات را به محض منسوخ شدن به null تغییر دهید. همچنین، به کشها توجه داشته باشید، که میتوانند ارجاعات اشیاء را مدتها پس از بیربط شدن نگهداری کنند. از WeakHashMap
برای کشهایی استفاده کنید که ورودیهای آنها تنها بهمدت وجود ارجاعات به کلیدهایشان در خارج از کش مرتبط هستند.
6. قرارداد Equals: بازتابی، تقارن و انتقال
متد equals یک رابطه معادل را پیادهسازی میکند.
رابطه معادل. هنگام بازنویسی متد equals
، رعایت قرارداد عمومی آن که یک رابطه معادل را تعریف میکند، بسیار مهم است. این قرارداد شامل بازتابی (x.equals(x) باید true برگرداند)، تقارن (x.equals(y) باید true باشد اگر و تنها اگر y.equals(x) true باشد) و انتقال (اگر x.equals(y) و y.equals(z) true باشند، آنگاه x.equals(z) باید true باشد) است.
نقض تقارن. نقض تقارن میتواند منجر به رفتار غیرقابل پیشبینی شود زمانی که اشیاء در مجموعهها استفاده میشوند. بهعنوان مثال، یک کلاس CaseInsensitiveString
که سعی در تعامل با رشتههای عادی دارد، میتواند تقارن را نقض کند.
نقض انتقال. نقض انتقال میتواند زمانی رخ دهد که یک کلاس قابل نمونهسازی را گسترش داده و جنبهای را اضافه کنید که بر مقایسههای equals
تأثیر بگذارد. برای جلوگیری از این موضوع، ترکیب را به ارثبری ترجیح دهید.
عدم وجود null. متد equals
باید برای هر مقدار مرجع غیر null x زمانی که x.equals(null) فراخوانی میشود، false برگرداند. عملگر instanceof
این موضوع را بهطور خودکار مدیریت میکند.
7. بازنویسی HashCode: سازگاری با Equals
شما باید hashCode را در هر کلاسی که equals را بازنویسی میکند، بازنویسی کنید.
اهمیت HashCode. بازنویسی hashCode
زمانی که equals
را بازنویسی میکنید، ضروری است تا اطمینان حاصل شود که اشیاء برابر دارای کدهای هش برابر هستند. عدم انجام این کار قرارداد عمومی Object.hashCode
را نقض کرده و از عملکرد صحیح کلاس در مجموعههای مبتنی بر هش مانند HashMap
و HashSet
جلوگیری میکند.
تابع هش قانونی اما ضعیف. یک متد hashCode
بیمعنا که همیشه همان مقدار را برمیگرداند قانونی است اما منجر به عملکرد ضعیف برای جداول هش میشود، زیرا تمام اشیاء به همان سطل هش میشوند.
دستورالعملی برای یک تابع هش خوب. یک تابع هش خوب تمایل دارد کدهای هش نابرابر برای اشیاء نابرابر تولید کند. یک دستورالعمل ساده شامل:
- مقداردهی اولیه یک متغیر
int
به نامresult
با یک مقدار ثابت غیر صفر (بهعنوان مثال، 17). - برای هر فیلد مهم
f
در شیء، یک کد هشc
محاسبه کرده و آن را با استفاده ازresult = 37 * result + c;
بهresult
ترکیب کنید. result
را برگردانید.
8. بازنویسی ToString: نمایش مختصر و اطلاعاتی
متد toString بهطور خودکار زمانی که شیء شما به println، عملگر الحاق رشته (+) یا، از نسخه 1.4 به بعد، assert منتقل میشود، فراخوانی میشود.
اهمیت ToString. بازنویسی متد toString
یک نمایش مختصر و اطلاعاتی از یک شیء فراهم میکند که استفاده از کلاس را دلپذیرتر میسازد. این موضوع بهویژه برای اشکالزدایی و ثبت وقایع مفید است.
محتوای ToString. زمانی که عملی باشد، متد toString
باید تمام اطلاعات جالب موجود در شیء را برگرداند. اگر شیء بزرگ باشد یا حاوی حالتی باشد که برای نمایش رشتهای مناسب نیست، باید یک خلاصه برگردانده شود.
تعیین فرمت. هنگام پیادهسازی toString
، تصمیم بگیرید که آیا فرمت مقدار بازگشتی را در مستندات مشخص کنید یا خیر. مشخص کردن فرمت یک نمایش استاندارد و بدون ابهام فراهم میکند اما انعطافپذیری برای تغییرات آینده را محدود میکند. اگر فرمت را مشخص کنید، یک سازنده رشته یا کارخانه استاتیک متناسب ارائه دهید.
9. رابط Cloneable: با احتیاط پیادهسازی کنید
رابط Cloneable بهعنوان یک رابط میکسین (ماده 16) برای اشیاء طراحی شده بود تا نشان دهد که آنها اجازه کپیبرداری را میدهند.
نقصهای Cloneable. رابط Cloneable
فاقد یک متد clone
است و متد clone
کلاس Object
محافظتشده است. این موضوع فراخوانی متد clone
بر روی یک شیء صرفاً به این دلیل که Cloneable
را پیادهسازی میکند، دشوار میسازد.
قرارداد Clone. قرارداد عمومی برای متد clone
ضعیف است و بیان میکند که یک کپی از شیء ایجاد و برمیگرداند. با این حال، مشخص نمیکند که این کپی چگونه باید ساخته شود یا آیا سازندهها باید فراخوانی شوند یا خیر.
پیادهسازی Cloneable. برای پیادهسازی صحیح Cloneable
، یک کلاس باید متد clone
را با یک متد عمومی که ابتدا super.clone
را فراخوانی کرده و سپس هر فیلدی که نیاز به اصلاح دارد را اصلاح میکند، بازنویسی کند. این معمولاً به معنای کپی کردن هر شیء قابل تغییر است که ساختار داخلی "عمیق" شیء را تشکیل میدهد.
جایگزینهای Cloneable. یک رویکرد خوب برای کپیبرداری از اشیاء، ارائه یک سازنده کپی یا کارخانه استاتیک است. این رویکردها به مکانیزم ایجاد شیء پرخطر وابسته نیستند و با استفاده صحیح از فیلدهای نهایی تداخل ندارند.
10. رابط Comparable: ترتیب طبیعی
با پیادهسازی Comparable، یک کلاس نشان میدهد که نمونههای آن دارای یک ترتیب طبیعی هستند.
مزایای Comparable. پیادهسازی رابط Comparable
به یک کلاس اجازه میدهد تا با الگوریتمهای عمومی و پیادهسازیهای مجموعه که به ترتیب وابسته هستند، مانند Arrays.sort
و TreeSet
، تعامل داشته باشد.
قرارداد CompareTo. قرارداد عمومی برای متد compareTo
مشابه قرارداد متد equals
است و نیاز به بازتابی، انتقال و تقارن دارد. به شدت توصیه میشود که (x.compareTo(y)==0) == (x.equals(y))
باشد.
نوشتن یک متد CompareTo. هنگام نوشتن یک متد compareTo
، فیلدهای مرجع شیء را با فراخوانی متد compareTo
بهطور بازگشتی مقایسه کنید. فیلدهای اولیه را با استفاده از عملگرهای رابطهای <
و >
مقایسه کنید. اگر یک کلاس چندین فیلد مهم داشته باشد، آنها را به ترتیب اهمیت مقایسه کنید.
11. حداقل کردن دسترسی: پنهانسازی اطلاعات
مهمترین عاملی که یک ماژول بهخوبی طراحیشده را از یک ماژول بهبدی طراحیشده متمایز میکند، درجهای است که ماژول دادههای داخلی و سایر جزئیات پیادهسازی خود را از سایر ماژولها پنهان میکند.
مزایای پنهانسازی اطلاعات. پنهانسازی اطلاعات یا کپسولهسازی ماژولها را از هم جدا میکند و به آنها اجازه میدهد بهطور مستقل توسعه، آزمایش، بهینهسازی و تغییر یابند. این موضوع سرعت توسعه سیستم را افزایش میدهد، نگهداری را آسانتر میکند، استفاده مجدد از نرمافزار را افزایش میدهد و ریسک را کاهش میدهد.
سطوح دسترسی. زبان برنامهنویسی جاوا اصلاحکنندههای دسترسی (private
، package-private، protected
و public
) را برای کمک به پنهانسازی اطلاعات فراهم میکند. قاعده کلی این است که هر کلاس یا عضوی را تا حد ممکن غیرقابل دسترسی کنید.
فیلدهای عمومی. کلاسهای عمومی باید بهندرت، اگر هرگز، فیلدهای عمومی داشته باشند (برخلاف متدهای عمومی). استثنا برای فیلدهای عمومی استاتیک نهایی حاوی مقادیر اولیه یا ارجاعات به اشیاء غیرقابل تغییر است.
12. ترجیح عدم تغییرپذیری: سادگی و ایمنی در برابر رشتهها
یک کلاس غیرقابل تغییر به سادگی کلاسی است که نمونههای آن نمیتوانند تغییر کنند.
مزایای عدم تغییرپذیری. کلاسهای غیرقابل تغییر از کلاسهای قابل تغییر آسانتر برای طراحی، پیادهسازی و استفاده هستند. آنها کمتر مستعد خطا هستند و ایمنترند.
قوانین برای عدم تغییرپذیری. برای غیرقابل تغییر کردن یک کلاس:
- هیچ متدی که شیء را تغییر دهد (متدهای تغییر دهنده) ارائه ندهید.
- اطمینان حاصل کنید که هیچ متدی قابل بازنویسی نیست (کلاس را نهایی کنید یا از سازندههای خصوصی و کارخانههای استاتیک استفاده کنید).
- تمام فیلدها را نهایی کنید.
- تمام فیلدها را خصوصی کنید.
- اطمینان حاصل کنید که دسترسی انحصاری به هر مؤلفه قابل تغییر وجود دارد (کپیهای دفاعی ایجاد کنید).
معایب عدم تغییرپذیری. تنها عیب واقعی کلاسهای غیرقابل تغییر این است که آنها به یک شیء جداگانه برای هر مقدار متمایز نیاز دارند. برای مقابله با این موضوع، مقادیر پرکاربرد را بهعنوان ثابتهای عمومی استاتیک نهایی ارائه دهید و در نظر بگیرید که یک کلاس همراه قابل تغییر عمومی ارائه دهید.
آخرین بهروزرسانی::
نقد و بررسی
کتاب جاوا مؤثر به عنوان یک منبع ضروری برای توسعهدهندگان جاوا شناخته میشود و به خاطر توضیحات روشن و مشاورههای عملیاش مورد تحسین قرار گرفته است. خوانندگان از تخصص بلچ و تمرکز کتاب بر نوشتن کدهای باکیفیت و قابل نگهداری قدردانی میکنند. بسیاری آن را برای هر دو گروه مبتدیان و برنامهنویسان با تجربه یک کتاب ضروری میدانند. این کتاب به بررسی ویژگیهای مختلف جاوا، بهترین شیوهها و دامهای رایج میپردازد. در حالی که برخی بخشها را قدیمی یا بیش از حد پیشرفته میدانند، اکثر افراد بر این باورند که این کتاب به طور قابل توجهی مهارتهای کدنویسی و درک پیچیدگیهای جاوا را بهبود میبخشد.
Similar Books






