JavaRush /وبلاگ جاوا /Random-FA /آداپتور الگوی طراحی

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

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

   void connectWithUsbCable();
}
این رابط USB ما با تنها روش قرار دادن کابل USB است:
public class MemoryCard {

   public void insert() {
       System.out.println("Карта памяти успешно вставлена!");
   }

   public void copyData() {
       System.out.println("Данные скопированы на компьютер!");
   }
}
این کلاس ما است که نقشه حافظه را پیاده سازی می کند. در حال حاضر 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 چه کاری انجام می دهد و چرا آداپتور است؟ ساده است. کلاس در حال تطبیق (نقشه حافظه) به یکی از فیلدهای آداپتور تبدیل می شود. این منطقی است، زیرا در زندگی واقعی نیز یک کارت را در داخل کارت خوان قرار می دهیم و آن نیز بخشی از آن می شود. برخلاف کارت حافظه، آداپتور یک رابط مشترک با کامپیوتر دارد. دارای کابل USB است، به این معنی که می تواند از طریق USB به دستگاه های دیگر متصل شود. بنابراین در برنامه کلاس ما CardReaderرابط USB را پیاده سازی می کند. اما در داخل این روش چه اتفاقی می افتد؟ و دقیقا همان چیزی که ما نیاز داریم اتفاق می افتد! آداپتور کار را به کارت حافظه ما واگذار می کند. از این گذشته، آداپتور خود هیچ کاری نمی کند؛ کارت خوان هیچ عملکرد مستقلی ندارد. کارش فقط اتصال کامپیوتر و کارت حافظه است تا کارت بتواند کار خود را انجام دهد و فایل ها را کپی کند! آداپتور ما به آن اجازه می دهد تا این کار را با ارائه رابط (روش) خود connectWithUsbCable()برای "نیازهای" کارت حافظه انجام دهد. بیایید نوعی برنامه مشتری ایجاد کنیم که شخصی را که می خواهد داده ها را از کارت حافظه کپی کند شبیه سازی می کند:
public class Main {

   public static void main(String[] args) {

       USB cardReader = new CardReader(new MemoryCard());
       cardReader.connectWithUsbCable();

   }
}
در نتیجه چه چیزی به دست آوردیم؟ خروجی کنسول:
Карта памяти успешно вставлена!
Данные скопированы на компьютер!
عالی، وظیفه ما با موفقیت انجام شد! در اینجا چند پیوند اضافی با اطلاعات مربوط به الگوی آداپتور وجود دارد:

کلاس های چکیده 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'a به رابط Reader'a. در ابتدا کلاس داشتیم InputStream. به خوبی کار می کند، اما فقط می تواند تک بایت ها را بخواند. علاوه بر این، ما یک کلاس انتزاعی داریم Reader. عملکرد بسیار خوبی دارد که ما واقعاً به آن نیاز داریم - می تواند شخصیت ها را بخواند! البته ما واقعاً به این فرصت نیاز داریم. اما در اینجا ما با یک مشکل کلاسیک روبرو هستیم که معمولا آداپتورها آن را حل می کنند - ناسازگاری رابط. چگونه خود را نشان می دهد؟ بیایید مستقیماً به مستندات اوراکل نگاه کنیم. در اینجا متدهای کلاس آمده است InputStream. Паттерн проектирования «Адаптер» - 4مجموعه ای از روش ها یک رابط است. همانطور که می بینید، read()این کلاس یک متد دارد (حتی در چندین نسخه)، اما فقط می تواند بایت ها را بخواند: بایت های جداگانه یا چندین بایت با استفاده از یک بافر. این گزینه برای ما مناسب نیست - ما می خواهیم شخصیت ها را بخوانیم. عملکرد مورد نیاز ما قبلاً در کلاس abstract پیاده سازی شده استReader . این را می توان در اسناد نیز مشاهده کرد. Паттерн проектирования «Адаптер» - 5با این حال، رابط های InputStream"a" و Reader"a" ناسازگار هستند! همانطور که می بینید، در همه پیاده سازی های متد، read()هم پارامترهای ارسال شده و هم مقادیر بازگشتی متفاوت است. و این جایی است که ما به آن نیاز داریم InputStreamReader! او به عنوان یک آداپتور بین کلاس های ما عمل خواهد کرد. همانطور که در مثال کارت خوان، که در بالا به آن نگاه کردیم، شیء کلاس "adapted" را به صورت "داخلی"، یعنی به سازنده کلاس آداپتور منتقل می کنیم. در مثال قبلی، یک شی را MemoryCardبه داخل منتقل کردیم CardReader. حالا آبجکت را InputStreamبه سازنده منتقل می کنیم InputStreamReader! به عنوان یک کیفیت، InputStreamاز متغیر آشنا استفاده می کنیم System.in:
public static void main(String[] args) {

   InputStreamReader inputStreamReader = new InputStreamReader(System.in);
}
و در واقع: با نگاه کردن به مستندات InputStreamReaderخواهیم دید که "اقتباس" موفقیت آمیز بود :) اکنون روش هایی در اختیار داریم که به ما امکان خواندن شخصیت ها را می دهد. Паттерн проектирования «Адаптер» - 6و اگرچه در ابتدا شیء ما System.in(رشته ای که به صفحه کلید متصل است) این اجازه را نمی داد، با ایجاد الگوی Adapter ، سازندگان زبان این مشکل را حل کردند. کلاس انتزاعی Reader، مانند اکثر کلاس های I/O، یک برادر دوقلو دارد - Writer. این همان مزیت بزرگ را دارد Reader- یک رابط کاربری مناسب برای کار با نمادها فراهم می کند. با جریان های خروجی، مشکل و راه حل آن مانند جریان های ورودی به نظر می رسد. کلاسی وجود دارد OutputStreamکه فقط می تواند بایت بنویسد. یک کلاس انتزاعی وجود دارد Writerکه می تواند با نمادها کار کند و دو رابط ناسازگار وجود دارد. این مشکل دوباره با موفقیت توسط الگوی آداپتور حل شد. با استفاده از یک کلاس، OutputStreamWriterما به راحتی می توانیم دو رابط کلاس را Writerبا OutputStreamیکدیگر "تطبیق دهیم". و با دریافت یک جریان بایت OutputStreamدر سازنده، با کمک 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