Design pattern هایی که هر برنامه نویس اندروید باید بداند
زمان مورد نیاز برای مطالعه : 8 دقیقهدر این مقاله شش Design pattern یا الگوی طراحی به شما معرفی میشود که هر برنامه نویس اندرویدی باید بداند زیرا که تاثیر بسیار مهمی بر روی تمیزی و کارایی کد شما دارد.
Design Pattern چیست ؟
یک design pattern یک راه حل تکرارپذیر برای یک مشکل مهندسی نرم افزار است. بر خلاف اکثر راه حل های خاص برنامه، design pattern ها در بسیاری از برنامه ها استفاده می شود. design pattern ها به عنوان محصولات نهایی در نظر گرفته نمی شوند. در عوض، آنها الگوهایی هستند که می توانند در موقعیت های مختلف اعمال شوند و می توانند در طول زمان بهبود یابند و یک ابزار مهندسی نرم افزار بسیار قوی را ایجاد کنند. از آنجا که سرعت توسعه هنگام استفاده از یک نمونه اولیه اثبات شده افزایش می یابد، توسعه دهندگان با استفاده از design pattern ها می توانند کارایی کدنویسی و خوانایی محصول نهایی را بهبود بخشند.
نکته : هدف این مقاله معرفی Design Pattern های مهم و توضیح مختصری از عملکرد آنها میباشد و توضیح کامل آن ها در این مقاله میسر نیست.بعد از اینکه با این پترن ها آشنا شدید حتما در مورد آنها سرچ و تحقیق کنید تا عمیقا اونها رو درک کنید.
Pattern #1 Singleton
Singleton کلاسی است که اجازه می دهد تنها یک نمونه(instance) از خودش ایجاد شود و به آن نمونه ایجاد شده دسترسی پیدا کند. Singleton شامل متغیرهای ثابت است که می تواند نمونه های منحصر به فرد و خصوصی خود را در خود جای دهد. در سناریوهایی استفاده می شود که کاربر بخواهد نمونه سازی(instantiation ) یک کلاس را فقط به یک شی محدود کند. این معمولا زمانی مفید است که یک single object برای هماهنگ کردن اقدامات(coordinate actions) در سراسر یک سیستم مورد نیاز باشد.
قوانین ساخت کلاس Singleton
برای ساختن کلاس Singleton قوانین زیر رعایت می شود:
۱.یک سازنده خصوصی(A private constructor)
۲.مرجع ایستا از کلاس خود(A static reference of its class)
۳.یک متد استاتیک(One static method)
۴.مرجع شی در دسترس گلوبال(Globally accessible object reference)
۵.سازگاری در چندین ترد یا رشته (Consistency across multiple threads)
مثال از Singleton
نمونه در کلاس java :
public class Singleton { private static Singleton instance = null; private Singleton() { } public static Singleton getInstance() { if (instance == null) { synchronized (Singleton.class) { if (instance == null) { instance = new Singleton(); } } } return instance; } }
نمونه در کلاس Kotlin :
Object Singleton { init { println("Hello Singleton") } }
Pattern #2 Factory
همانطور که از نام آن پیداست، Factory از تمام منطق ایجاد شی مراقبت می کند. در این الگو، یک کلاس Factory کنترل می کند که کدام شی باید نمونه سازی شود. الگوی Factory هنگام برخورد با بسیاری از اشیاء رایج مفید است. شما می توانید از آن در جایی استفاده کنید که ممکن است نخواهید یک کلاس را مشخص کنید.
برای درک بهتر مطلب به کد زیر دقت کنید تا به نحوه کار با پترن Factory آشنا شوید :
interface Currency { fun symbol(): String fun code(): String } enum class Country { UnitedState, Spain } class USDollar : Currency { override fun symbol(): String { return "$" } override fun code(): String { return "USD" } } class Euro : Currency { override fun symbol(): String { return "€" } override fun code(): String { return "EUR" } } object CurrencyFactory { fun currency(country: Country): Currency { return when (country) { Country.UnitedState -> { USDollar() } Country.Spain -> { Euro() } } } }
Pattern #3 Builder
هدف الگوی سازنده(Builder) این است که “ساخت یک شی پیچیده را از نمایش آن جدا کند تا فرآیند construction یکسان بتواند بازنمایی های متفاوتی ایجاد کند.” برای ساختن یک شی پیچیده گام به گام استفاده می شود و مرحله نهایی آن شی را برمی گرداند.
نمونه اون رو هنگام ساخت Alert Dialog دیدید که قدم به قدم از شما اطلاعات شی رو دریافت میکنه و در انتها شی مورد نظر رو برای شما میسازه.
قوانین ساخت Builder :
۱.کانستراکتور خصوصی (A private constructor)
۲.یک کلاس داخلی که معمولاً Builder نامیده می شود.
۳.تابع برای هر Field به منظور تنظیم مقدار بازگشتی Field
۴.نمونه بازگشتی ساخت تابع از کلاس main
با خواندن مثال زیر کاملا متوجه طریقه استفاده Builder آشنا میشید :
class Hamburger private constructor( val cheese: Boolean, val beef: Boolean, val onions: Boolean ) { class Builder { private var cheese: Boolean = true private var beef: Boolean = true private var onions: Boolean = true fun cheese(value: Boolean) = apply { cheese = value } fun beef(value: Boolean) = apply { beef = value } fun onions(value: Boolean) = apply { onions = value } fun build() = Hamburger(cheese, beef, onions) } }
Pattern #4 Facade
الگوی Facade یک رابط(interface) سطح بالاتری را ارائه می دهد که استفاده از مجموعه ای از رابط های دیگر را آسان تر می کند. کد زیر زیر این ایده را بیشتر نشان می دهد.
interface BooksApi { @GET("books") fun listBooks(): Call<List<Book>> }
Square’s Retrofit یک کتابخانه اندروید منبع باز(open source) است که به شما کمک می کند الگوی facade را پیاده سازی کنید. شما یک اینترفیس ایجاد می کنید تا داده های API را به کلاینت ارائه دهید.
Pattern #5 Dependency Injection
تزریق وابستگی مانند نقل مکان به یک آپارتمان مبله است. هر چیزی که نیاز دارید از قبل وجود دارد. لازم نیست منتظر تحویل مبلمان باشید یا صفحات دستورالعمل های سایت دکوراسیون IKEA را دنبال کنید تا آن را جمع و خرید کنید.
در اصطلاح نرم افزاری، تزریق وابستگی به شما امکان می دهد هر object مورد نیاز را برای نمونه سازی یک object جدید ارائه دهید. این object جدید نیازی به ساخت یا سفارشی سازی خود object ها ندارد.
در Android، ممکن است متوجه شوید که باید از نقاط مختلف برنامه خود به همان object های پیچیده دسترسی داشته باشید، مانند network client، image loader یا SharedPreferences برای ذخیره سازی محلی. شما می توانید این object ها را به اکتیویتی ها و فرگمنت های خود تزریق کنید و بلافاصله به آنها دسترسی داشته باشید.
در اینجا یک مثالی آورده ایم. بدون تزریق وابستگی
نمایش خودرویی که وابستگی موتور خود را در کد ایجاد میکند به این صورت است:
class Car { private val engine = Engine() fun start() { engine.start() } } fun main(args: Array) { val car = Car() car.start() }
این نمونه ای از تزریق وابستگی نیست چون که کلاس Car در حال ساخت موتور خود است. این کار می تواند مشکل ساز باشد.
کد با تزریق وابستگی چگونه به نظر می رسد؟ به جای اینکه هر نمونه از Car شی Engine خود را در مقدار دهی اولیه بسازد، یک شی Engine را به عنوان پارامتر در سازنده خود دریافت می کند:
به کد زیر دقت کنید :
class Car(private val engine: Engine) { fun start() { engine.start() } } fun main(args: Array) { val engine = Engine() val car = Car(engine) car.start() }
Pattern #6 Adapter
الگوی adapter به عنوان پلی بین دو interface ناسازگار عمل می کند.
این الگو شامل یک کلاس واحد(single class) است که مسئول پیوستن به عملکردهای(functionalities ) اینترفیس های مستقل یا ناسازگار است. یک مثال واقعی می تواند یک رم ریدر(card reader) باشد که به عنوان آداپتور بین کارت حافظه و لپ تاپ عمل می کند. کارت حافظه را به رم ریدر و سپس رم ریدر را به لپ تاپ وصل می کنید تا کارت حافظه از طریق لپ تاپ قابل خواندن باشد.
توضیح کامل این Pattern رو میتوانید در اینجا مطالعه کنید.
جمع بندی
شاید مطالب بالا کمی نا مفهوم باشه اما اصلا نگران نباشید.با تحقیق و دیدن کلیپ های آموزشی و همچنین در یوتیوب شما کامل میتونید عملکرد هر Design Pattern رو درک کنید.
موفق و پیروز باشید
منبع : Medium.com
سایت خوب با مقالاتی بسیار بی نظیری دارین
لطف داری عزیزم 🙂