JavaRush /Java blogi /Random-UZ /Adapter dizayni namunasi qanday muammolarni hal qiladi?

Adapter dizayni namunasi qanday muammolarni hal qiladi?

Guruhda nashr etilgan
Dasturiy ta'minotni ishlab chiqish ko'pincha bir-biri bilan ishlaydigan komponentlar o'rtasidagi nomuvofiqlik tufayli murakkablashadi. Misol uchun, agar siz yangi kutubxonani Java-ning oldingi versiyalarida yozilgan eski platforma bilan birlashtirishingiz kerak bo'lsa, siz ob'ektlarning, aniqrog'i, interfeyslarning mos kelmasligiga duch kelishingiz mumkin. Bu holatda nima qilish kerak? Kod qayta yozilsinmi? Ammo bu mumkin emas: tizimni tahlil qilish juda ko'p vaqtni oladi yoki ishning ichki mantig'i buziladi. Adapter dizayni namunasi qanday muammolarni hal qiladi - 1Ushbu muammoni hal qilish uchun ular mos kelmaydigan interfeyslarga ega ob'ektlarning birgalikda ishlashiga yordam beradigan Adapter naqshini ishlab chiqdilar. Keling, undan qanday foydalanishni ko'rib chiqaylik!

Muammo haqida batafsil ma'lumot

Birinchidan, eski tizimning xatti-harakatlarini simulyatsiya qilaylik. Aytaylik, bu ish yoki maktabga kechikish sabablarini keltirib chiqaradi. Buning uchun biz , va usullarini Excuseo'z ichiga olgan interfeysga egamiz . generateExcuse()likeExcuse()dislikeExcuse()
public interface Excuse {
   String generateExcuse();
   void likeExcuse(String excuse);
   void dislikeExcuse(String excuse);
}
Ushbu interfeys sinf tomonidan amalga oshiriladi WorkExcuse:
public class WorkExcuse implements Excuse {
   private String[] reasonOptions = {"по невероятному стечению обстоятельств у нас в доме закончилась горячая вода и я ждал, пока солнечный свет, сконцентрированный через лупу, нагреет кружку воды, чтобы я мог умыться.",
   "искусственный интеллект в моем будильнике подвел меня и разбудил на час раньше обычного. Поскольку сейчас зима, я думал что еще ночь и уснул. Дальше все How в тумане.",
   "предпраздничное настроение замедляет метаболические процессы в моем организме и приводит к подавленному состоянию и бессоннице."};
   private String[] sorryOptions = {"Это, конечно, не повторится, мне очень жаль.", "Прошу меня извинить за непрофессиональное поведение.", "Нет оправдания моему поступку. Я недостоин этой должности."};

   @Override
   public String generateExcuse() { // Случайно выбираем отговорку из массива
       String result = "Я сегодня опоздал, потому что " + reasonOptions[(int) Math.round(Math.random() + 1)] + "\n" +
               sorryOptions[(int) Math.round(Math.random() + 1)];
       return result;
   }

   @Override
   public void likeExcuse(String excuse) {
       // Дублируем элемент в массиве, чтобы шанс его выпадения был выше
   }

   @Override
   public void dislikeExcuse(String excuse) {
       // Удаляем элемент из массива
   }
}
Keling, misolni sinab ko'raylik:
Excuse excuse = new WorkExcuse();
System.out.println(excuse.generateExcuse());
Xulosa:
Я сегодня опоздал, потому что предпраздничное настроение замедляет метаболические процессы в моем организме и приводит к подавленному состоянию и бессоннице. 
Прошу меня извинить за непрофессиональное поведение.
Endi tasavvur qilaylik, siz xizmatni ishga tushirdingiz, statistik ma'lumotlarni to'pladingiz va xizmatdan foydalanuvchilarning aksariyati universitet talabalari ekanligini payqadingiz. Uni ushbu guruh ehtiyojlari uchun yaxshilash uchun siz boshqa ishlab chiquvchidan uning uchun maxsus uzr yaratish tizimini buyurdingiz. Ishlab chiqish guruhi tadqiqot o'tkazdi, reytinglarni tuzdi, sun'iy intellektni bog'ladi, tirbandlik, ob-havo va hokazolar bilan integratsiyani qo'shdi. Endi sizda talabalar uchun bahonalar yaratish uchun kutubxonangiz bor, lekin u bilan ishlash interfeysi boshqacha - StudentExcuse:
public interface StudentExcuse {
   String generateExcuse();
   void dislikeExcuse(String excuse);
}
Interfeysda ikkita usul mavjud: generateExcuse, uzr hosil qiluvchi va dislikeExcuse, uzrni kelajakda paydo bo'lmasligi uchun bloklaydi. Uchinchi tomon kutubxonasi tahrirlash uchun yopilgan - siz uning manba kodini o'zgartira olmaysiz. Natijada, tizimingizda interfeysni amalga oshiradigan ikkita sinf va interfeysni amalga oshiradigan Excusesinfga ega kutubxona mavjud : SuperStudentExcuseStudentExcuse
public class SuperStudentExcuse implements StudentExcuse {
   @Override
   public String generateExcuse() {
       // Логика нового функционала
       return "Невероятная отговорка, адаптированная под текущее состояние погоды, пробки or сбои в расписании общественного транспорта.";
   }

   @Override
   public void dislikeExcuse(String excuse) {
       // Добавляет причину в черный список
   }
}
Kodni o'zgartirib bo'lmaydi. Joriy sxema quyidagicha ko'rinishga ega bo'ladi: Adapter - 2 dizayn namunasi qanday muammolarni hal qiladi?Tizimning ushbu versiyasi faqat Excuse interfeysi bilan ishlaydi. Siz kodni qayta yoza olmaysiz: katta dasturda bunday o'zgarishlar uzoq vaqt talab qilishi yoki dastur mantig'ini buzishi mumkin. Siz asosiy interfeysni joriy etish va ierarxiyani oshirishni taklif qilishingiz mumkin: Adapter dizayn namunasi qanday muammolarni hal qiladi - 3Buni amalga oshirish uchun interfeys nomini o'zgartirishingiz kerak Excuse. Ammo jiddiy ilovalarda qo'shimcha ierarxiya istalmagan: umumiy ildiz elementini kiritish arxitekturani buzadi. Siz yangi va eski funksiyalarni minimal yo'qotish bilan ishlatishga imkon beradigan oraliq sinfni amalga oshirishingiz kerak. Qisqasi, sizga adapter kerak .

Adapter namunasi qanday ishlaydi

Adapter - bu bir ob'ektdagi usullarga qo'ng'iroqlarni boshqasiga tushunarli qiladigan oraliq ob'ekt. Keling, misolimiz uchun adapterni amalga oshiramiz va uni chaqiramiz Middleware. Bizning adapterimiz ob'ektlardan biriga mos keladigan interfeysni amalga oshirishi kerak. Tinch qo'y, hamma narsa o'z holidagiday qo'sin; shunday bo'lsin Excuse. Buning yordamida Middlewareu birinchi ob'ektning usullarini chaqirishi mumkin. Middlewareqo'ng'iroqlarni qabul qiladi va ularni mos formatda ikkinchi ob'ektga uzatadi. MiddlewareUsullar bilan usulni amalga oshirish generateExcusequyidagicha ko'rinadi dislikeExcuse:
public class Middleware implements Excuse { // 1. Middleware становится совместимым с an objectом WorkExcuse через интерфейс Excuse

   private StudentExcuse superStudentExcuse;

   public Middleware(StudentExcuse excuse) { // 2. Получаем ссылку на адаптируемый an object
       this.superStudentExcuse = excuse;
   }

   @Override
   public String generateExcuse() {
       return superStudentExcuse.generateExcuse(); // 3. Адаптер реализовывает метод интерфейса
   }

    @Override
    public void dislikeExcuse(String excuse) {
        // Метод предварительно помещает отговорку в черный список БД,
        // Затем передает ее в метод dislikeExcuse an object superStudentExcuse.
    }
   // Метод likeExcuse появятся позже
}
Sinov (mijoz kodida):
public class Test {
   public static void main(String[] args) {
       Excuse excuse = new WorkExcuse(); // Создаются an objectы классов,
       StudentExcuse newExcuse = new SuperStudentExcuse(); // Которые должны быть совмещены.
       System.out.println("Обычная причина для работника:");
       System.out.println(excuse.generateExcuse());
       System.out.println("\n");
       Excuse adaptedStudentExcuse = new Middleware(newExcuse); // Оборачиваем новый функционал в an object-адаптер
       System.out.println("Использование нового функционала с помощью адаптера:");
       System.out.println(adaptedStudentExcuse.generateExcuse()); // Адаптер вызывает адаптированный метод
   }
}
Xulosa:
Обычная причина для работника:
Я сегодня опоздал, потому что предпраздничное настроение замедляет метаболические процессы в моем организме и приводит к подавленному состоянию и бессоннице.
Нет оправдания моему поступку. Я недостоин этой должности. Использование нового функционала с помощью адаптера
Hozirgi ob-havo sharoitlariga, tirbandliklarga yoki jamoat transporti jadvalidagi buzilishlarga moslashtirilgan aql bovar qilmaydigan bahona. Usul generateExcuseqo'shimcha o'zgarishlarsiz qo'ng'iroqni boshqa ob'ektga o'tkazadi. Usul dislikeExcuseavval uzrni ma'lumotlar bazasi qora ro'yxatiga joylashtirishni talab qildi. Qo'shimcha oraliq ma'lumotlarni qayta ishlash Adapter naqshini sevish sababidir. likeExcuseLekin interfeysda bo'lgan Excuse, lekin ichida bo'lmagan usul haqida nima deyish mumkin StudentExcuse? Ushbu operatsiya yangi funksiyada qo'llab-quvvatlanmaydi. Bunday holatda, ular istisno bilan kelishdi UnsupportedOperationException: agar so'ralgan operatsiya qo'llab-quvvatlanmasa, u tashlanadi. Keling, buni ishlataylik. Yangi sinfni amalga oshirish shunday ko'rinadi Middleware:
public class Middleware implements Excuse {

   private StudentExcuse superStudentExcuse;

   public Middleware(StudentExcuse excuse) {
       this.superStudentExcuse = excuse;
   }

   @Override
   public String generateExcuse() {
       return superStudentExcuse.generateExcuse();
   }

   @Override
   public void likeExcuse(String excuse) {
       throw new UnsupportedOperationException("Метод likeExcuse не поддерживается в новом функционале");
   }

   @Override
   public void dislikeExcuse(String excuse) {
       // Метод обращается за дополнительной информацией к БД,
       // Затем передает ее в метод dislikeExcuse an object superStudentExcuse.
   }
}
Bir qarashda, bu yechim muvaffaqiyatli ko'rinmaydi, ammo funksionallikni simulyatsiya qilish yanada murakkab vaziyatga olib kelishi mumkin. Agar mijoz diqqatli bo'lsa va adapter yaxshi hujjatlashtirilgan bo'lsa, bu yechim qabul qilinadi.

Adapterdan qachon foydalanish kerak

  1. Agar siz uchinchi tomon sinfidan foydalanishingiz kerak bo'lsa, lekin uning interfeysi asosiy dastur bilan mos kelmasa. Yuqoridagi misol qo'ng'iroqlarni maqsadli ob'ekt uchun tushunarli formatda o'rab oladigan shim ob'ekti qanday yaratilganligini ko'rsatadi.

  2. Bir nechta mavjud kichik sinflar umumiy funksionallikka ega bo'lishi kerak bo'lganda. Qo'shimcha kichik sinflar o'rniga (ularning yaratilishi kodning takrorlanishiga olib keladi), adapterdan foydalanish yaxshiroqdir.

Afzalliklar va kamchiliklar

Afzallik: adapter mijozdan bir ob'ektdan ikkinchisiga so'rovlarni qayta ishlash tafsilotlarini yashiradi. Mijoz kodi ma'lumotlarni formatlash yoki maqsadli usulga qo'ng'iroqlarni qayta ishlash haqida o'ylamaydi. Bu juda murakkab va dasturchilar dangasa :) Kamchilik: Loyihaning kod bazasi qo'shimcha sinflar bilan murakkablashadi va agar mos kelmaydigan nuqtalar ko'p bo'lsa, ularning soni nazorat qilib bo'lmaydigan o'lchamlarga qadar o'sishi mumkin.

Fasad va dekorativ bilan adashtirmaslik kerak

Yuzaki tekshirilganda, adapterni Fasad va Dekorator naqshlari bilan aralashtirish mumkin. Adapter va Fasad o'rtasidagi farq shundaki, Fasad yangi interfeysni taqdim etadi va butun quyi tizimni qamrab oladi. Xo'sh, Dekorator, Adapterdan farqli o'laroq, interfeysni emas, balki ob'ektni o'zi o'zgartiradi.

Bosqichma-bosqich amalga oshirish algoritmi

  1. Birinchidan, ushbu naqsh hal qila oladigan muammo borligiga ishonch hosil qiling.

  2. Boshqa sinf nomidan foydalaniladigan mijoz interfeysini aniqlang.

  3. Oldingi bosqichda belgilangan interfeysga asoslangan adapter sinfini amalga oshiring.

  4. Adapter sinfida ob'ektga havolani saqlaydigan maydon yarating. Ushbu havola konstruktorda uzatiladi.

  5. Adapterda barcha mijoz interfeysi usullarini amalga oshiring. Usul quyidagicha bo'lishi mumkin:

    • Qo'ng'iroqni o'zgartirmasdan o'tkazish;

    • Ma'lumotlarni o'zgartirish, maqsadli usulga qo'ng'iroqlar sonini oshirish/kamaytirish, ma'lumotlar tarkibini yanada kengaytirish va h.k.

    • Oxirgi chora sifatida, agar ma'lum bir usul mos kelmasa, qat'iy hujjatlashtirilishi kerak bo'lgan UnsupportedOperationException-ni tashlang.

  6. Agar dastur adapterni faqat mijoz interfeysi orqali ishlatsa (yuqoridagi misolda bo'lgani kabi), bu kelajakda adapterlarni og'riqsiz uzaytirish imkonini beradi.

Albatta, dizayn namunasi barcha kasalliklar uchun panatseya emas, lekin uning yordami bilan siz turli xil interfeyslarga ega bo'lgan ob'ektlarning mos kelmasligi muammosini oqlangan tarzda hal qilishingiz mumkin. Asosiy naqshlarni biladigan dasturchi oddiygina algoritmlarni yozishni biladiganlardan bir necha qadam yuqori, chunki ular jiddiy ilovalar yaratish uchun kerak. Kodni qayta ishlatish qiyinroq bo'ladi va uni saqlash juda yoqimli. Bugun hammasi shu! Ammo biz tez orada turli dizayn naqshlari bilan tanishuvimizni davom ettiramiz :)
Izohlar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION