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 usullariniExcuse
o'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 Excuse
sinfga ega kutubxona mavjud : SuperStudentExcuse
StudentExcuse
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: 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: Buni 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 chaqiramizMiddleware
. 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 Middleware
u birinchi ob'ektning usullarini chaqirishi mumkin. Middleware
qo'ng'iroqlarni qabul qiladi va ularni mos formatda ikkinchi ob'ektga uzatadi. Middleware
Usullar bilan usulni amalga oshirish generateExcuse
quyidagicha 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 generateExcuse
qo'shimcha o'zgarishlarsiz qo'ng'iroqni boshqa ob'ektga o'tkazadi. Usul dislikeExcuse
avval uzrni ma'lumotlar bazasi qora ro'yxatiga joylashtirishni talab qildi. Qo'shimcha oraliq ma'lumotlarni qayta ishlash Adapter naqshini sevish sababidir. likeExcuse
Lekin 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
-
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.
-
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
-
Birinchidan, ushbu naqsh hal qila oladigan muammo borligiga ishonch hosil qiling.
-
Boshqa sinf nomidan foydalaniladigan mijoz interfeysini aniqlang.
-
Oldingi bosqichda belgilangan interfeysga asoslangan adapter sinfini amalga oshiring.
-
Adapter sinfida ob'ektga havolani saqlaydigan maydon yarating. Ushbu havola konstruktorda uzatiladi.
-
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.
-
-
Agar dastur adapterni faqat mijoz interfeysi orqali ishlatsa (yuqoridagi misolda bo'lgani kabi), bu kelajakda adapterlarni og'riqsiz uzaytirish imkonini beradi.
GO TO FULL VERSION