CodeGym /وبلاگ جاوا /Random-FA /الگوی طراحی آداپتور
John Squirrels
مرحله
San Francisco

الگوی طراحی آداپتور

در گروه منتشر شد
سلام! امروز به یک موضوع جدید مهم خواهیم پرداخت: الگوهای طراحی . این الگوها چیست؟ من فکر می کنم شما باید عبارت " چرخ را دوباره اختراع نکنید " را بدانید. در برنامه نویسی، مانند بسیاری از زمینه های دیگر، تعداد زیادی موقعیت رایج وجود دارد. همانطور که توسعه نرم افزار تکامل یافته است، راه حل های آماده ای که برای هر یک از آنها کار می کند ایجاد شده است. این راه حل ها الگوهای طراحی نامیده می شوند. طبق قرارداد، یک الگو راه حلی است که به این صورت فرموله شده است: "اگر باید X را در برنامه خود انجام دهید، این بهترین راه برای انجام آن است". الگوهای زیادی وجود دارد. کتاب عالی الگوهای طراحی اول سر که حتما باید با آن آشنا شوید تقدیم به آنها. الگوی طراحی آداپتور - 2به طور خلاصه، یک الگو شامل یک مسئله مشترک و یک راه حل مربوطه است که می تواند نوعی استاندارد در نظر گرفته شود. در درس امروز با یکی از این الگوها آشنا می شویم: آداپتور. نام آن گویای همه چیز است و شما بارها در زندگی واقعی با آداپتورها روبرو شده اید. برخی از رایج ترین آداپتورها کارتخوان هایی هستند که بسیاری از رایانه ها و لپ تاپ ها دارند. الگوی طراحی آداپتور - 3فرض کنید ما نوعی کارت حافظه داریم. پس مشکل چیست؟ نمی داند چگونه با کامپیوتر ارتباط برقرار کند. آنها رابط مشترکی ندارند. رایانه دارای پورت USB است، اما نمی توانیم کارت حافظه را در آن قرار دهیم. کارت را نمی‌توان به رایانه وصل کرد، بنابراین نمی‌توانیم عکس‌ها، ویدیوها و سایر داده‌های خود را ذخیره کنیم. کارت خوان آداپتوری است که این مشکل را حل می کند. بالاخره کابل USB داره! برخلاف خود کارت، کارتخوان را می توان به کامپیوتر وصل کرد. آنها یک رابط مشترک با رایانه دارند: USB. بیایید ببینیم که در عمل چگونه به نظر می رسد:

public interface USB { 

   void connectWithUsbCable(); 
}
این رابط USB ما با تنها یک روش برای اتصال از طریق USB است.

public class MemoryCard { 

   public void insert() { 
       System.out.println("Memory card successfully inserted!"); 
   } 

   public void copyData() { 
       System.out.println("The data has been copied to the computer!"); 
   } 
}
این کلاس ما کارت حافظه است. قبلاً 2 روش مورد نیاز ما را دارد، اما مشکل اینجاست: رابط USB را پیاده سازی نمی کند. کارت را نمی توان در پورت USB قرار داد.

public class CardReader implements USB { 

   private MemoryCard memoryCard; 

   public CardReader(MemoryCard memoryCard) { 
       this.memoryCard = memoryCard; 
   } 

   @Override 
   public void connectWithUsbCable() { 
       this.memoryCard.insert(); 
       this.memoryCard.copyData(); 
   } 
}
و آداپتور ما اینجاست! کلاس چه کاری CardReaderانجام می دهد و دقیقاً چه چیزی آن را به یک آداپتور تبدیل می کند؟ همه چیز ساده است. کلاس در حال تطبیق (MemoryCard) به یکی از فیلدهای آداپتور تبدیل می شود. این منطقی است. وقتی در زندگی واقعی یک کارت حافظه را داخل یک کارت خوان قرار می دهیم، آن نیز بخشی از آن می شود. برخلاف کارت حافظه، آداپتور یک رابط مشترک با رایانه دارد. دارای کابل USB است یعنی از طریق USB به دستگاه های دیگر متصل می شود. به همین دلیل است که کلاس CardReader ما رابط USB را پیاده سازی می کند. اما دقیقا در داخل این روش چه اتفاقی می افتد؟ دقیقاً همان چیزی است که باید اتفاق بیفتد! آداپتور کار را به کارت حافظه ما واگذار می کند. در واقع، آداپتور به خودی خود کاری انجام نمی دهد. کارتخوان هیچ عملکرد مستقلی ندارد. وظیفه آن فقط اتصال کامپیوتر و کارت حافظه است تا به کارت اجازه دهد کار خود را انجام دهد - کپی کردن فایل ها! آداپتور ما این کار را با ارائه رابط خود ( connectWithUsbCable()روش) برای پاسخگویی به "نیازهای" کارت حافظه فعال می کند. بیایید یک برنامه مشتری ایجاد کنیم که فردی را که می خواهد داده ها را از کارت حافظه کپی کند شبیه سازی می کند:

public class Main { 

   public static void main(String[] args) { 

       USB cardReader = new CardReader(new MemoryCard()); 
       cardReader.connectWithUsbCable(); 
   } 
}
پس چی به دست آوردیم؟ خروجی کنسول:

Memory card successfully inserted! 
The data has been copied to the computer!
عالی ما به هدف خود رسیدیم! در اینجا پیوندی به یک ویدیو با اطلاعاتی در مورد الگوی آداپتور وجود دارد:

کلاس های انتزاعی Reader و Writer

اکنون ما به فعالیت مورد علاقه خود باز خواهیم گشت: یادگیری در مورد چند کلاس جدید برای کار با ورودی و خروجی :) من نمی دانم که قبلاً در مورد چند کلاس یاد گرفته ایم. Reader امروز در مورد و کلاس ها صحبت خواهیم کرد Writer. چرا به طور خاص آن کلاس ها؟ زیرا آنها مربوط به بخش قبلی ما در مورد آداپتورها هستند. بیایید آنها را با جزئیات بیشتری بررسی کنیم. ما با شروع خواهیم کرد  Reader. Readerیک کلاس انتزاعی است، بنابراین نمی‌توانیم اشیاء را به‌صراحت ایجاد کنیم.   اما شما در واقع از قبل با آن آشنا هستید! BufferedReaderاز این گذشته، شما به خوبی با و InputStreamReaderطبقات، که فرزندان آن هستند آشنا هستید :)

public class BufferedReader extends Reader {} 

public class InputStreamReader extends Reader {}
کلاس InputStreamReaderیک آداپتور کلاسیک است. همانطور که احتمالاً به خاطر دارید، می توانیم یک InputStreamشی را به سازنده آن ارسال کنیم. برای این کار معمولا از System.inمتغیر استفاده می کنیم:

public static void main(String[] args) { 

   InputStreamReader inputStreamReader = new InputStreamReader(System.in); 
}
اما چه می InputStreamReaderکند؟ مانند هر آداپتور، یک رابط را به دیگری تبدیل می کند.  در این مورد، InputStreamرابط به Readerرابط. در ابتدا، ما کلاس داریم InputStream. به خوبی کار می کند، اما شما فقط می توانید از آن برای خواندن تک بایت ها استفاده کنید. Readerعلاوه بر این، ما یک کلاس انتزاعی داریم . عملکرد بسیار مفیدی دارد - می داند چگونه کاراکترها را بخواند! ما قطعا به این توانایی نیاز داریم. اما در اینجا با مشکل کلاسیکی روبرو هستیم که معمولاً توسط آداپتورها حل می شود - رابط های ناسازگار. معنی آن چیست؟ بیایید نگاهی به مستندات اوراکل بیندازیم. در اینجا متدهای کلاس آمده است InputStream. الگوی طراحی آداپتور - 4مجموعه ای از روش ها دقیقاً همان رابط هستند. همانطور که می بینید، این کلاس یک read()متد دارد (در واقع چند نوع مختلف)، اما فقط می تواند بایت ها را بخواند: بایت های جداگانه یا چندین بایت با استفاده از یک بافر. اما این گزینه برای ما مناسب نیست - ما می خواهیم شخصیت ها را بخوانیم. ما به عملکردی نیاز داریم که قبلاً در Readerکلاس abstract پیاده سازی شده است . ما همچنین می توانیم این را در مستندات مشاهده کنیم. الگوی طراحی آداپتور - 5با این حال، InputStreamو  Readerرابط ها ناسازگار هستند! همانطور که می بینید، هر پیاده سازی متد read()دارای پارامترها و مقادیر بازگشتی متفاوتی است. و این جایی است که ما نیاز داریم InputStreamReader! به عنوان یک آداپتور بین کلاس های ما عمل خواهد کرد . مانند مثال کارت خوان، که در بالا در نظر گرفتیم، نمونه ای از کلاس در حال تطبیق را در "داخل" کلاس آداپتور قرار می دهیم، یعنی یکی را به سازنده آن ارسال می کنیم. در مثال قبلی، یک MemoryCardشی را داخل آن قرار دادیم CardReader. InputStream اکنون یک شی را به سازنده می‌دهیم InputStreamReader! ما از System.inمتغیر آشنا به صورت زیر استفاده می کنیم InputStream:

public static void main(String[] args) { 

   InputStreamReader inputStreamReader = new InputStreamReader(System.in); 
}
و در واقع، با نگاه کردن به مستندات InputStreamReader، می‌توانیم ببینیم که اقتباس موفق بوده است :) اکنون روش‌هایی برای خواندن شخصیت‌ها در اختیار داریم. الگوی طراحی آداپتور - 6و اگرچه شی ما System.in(جریان متصل به صفحه کلید) در ابتدا این اجازه را نمی داد، سازندگان زبان این مشکل را با اجرای الگوی آداپتور حل کردند. کلاس Readerانتزاعی، مانند اکثر کلاس های I/O، یک برادر دوقلو دارد —  Writer. این همان مزیت بزرگ را دارد  Reader - یک رابط کاربری مناسب برای کار با شخصیت ها فراهم می کند. با جریان های خروجی، مشکل و راه حل آن مانند جریان های ورودی به نظر می رسد. یک کلاس وجود دارد OutputStreamکه فقط می تواند بایت بنویسد، یک کلاس انتزاعی وجود دارد Writerکه می داند چگونه با کاراکترها کار کند، و دو رابط ناسازگار وجود دارد. این مشکل یک بار دیگر با الگوی آداپتور حل می شود. ما از OutputStreamWriterکلاس برای تطبیق آسان دو رابط کلاس Writer و  OutputStream با یکدیگر استفاده می کنیم. پس از ارسال یک OutputStreamجریان بایت به سازنده، می توانیم از an OutputStreamWriterبرای نوشتن کاراکترها به جای بایت استفاده کنیم!

import java.io.*; 

public class Main { 

   public static void main(String[] args) throws IOException { 

       OutputStreamWriter streamWriter = new OutputStreamWriter(new FileOutputStream("C:\\Users\\Username\\Desktop\\test.txt")); 
       streamWriter.write(32144); 
       streamWriter.close();
   } 
}
ما کاراکتر را با کد 32144 (綐) در فایل خود نوشتیم و دیگر نیازی به کار با بایت نیست :) همین امروز است. در درس های بعدی می بینمت! :)
نظرات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION