JavaRush /Blog Java /Random-MS /Apakah masalah yang diselesaikan oleh corak reka bentuk P...

Apakah masalah yang diselesaikan oleh corak reka bentuk Penyesuai?

Diterbitkan dalam kumpulan
Pembangunan perisian selalunya rumit oleh ketidakserasian antara komponen yang berfungsi antara satu sama lain. Contohnya, jika anda perlu menyepadukan perpustakaan baharu dengan platform lama yang ditulis dalam versi Java yang lebih awal, anda mungkin menghadapi ketidakserasian objek, atau lebih tepat lagi, antara muka. Apa yang perlu dilakukan dalam kes ini? Tulis semula kod? Tetapi ini adalah mustahil: menganalisis sistem akan mengambil banyak masa atau logik dalaman kerja akan rosak. Apakah masalah yang diselesaikan oleh corak reka bentuk Penyesuai - 1Untuk menyelesaikan masalah ini, mereka menghasilkan corak Penyesuai, yang membantu objek dengan antara muka yang tidak serasi berfungsi bersama. Mari lihat cara menggunakannya!

Butiran lanjut tentang masalah tersebut

Mula-mula, mari kita simulasi tingkah laku sistem lama. Katakan ia menjana sebab untuk lewat ke tempat kerja atau sekolah. Untuk melakukan ini, kami mempunyai antara muka Excuseyang mengandungi kaedah generateExcuse(), likeExcuse()dan dislikeExcuse().
public interface Excuse {
   String generateExcuse();
   void likeExcuse(String excuse);
   void dislikeExcuse(String excuse);
}
Antara muka ini dilaksanakan oleh kelas 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) {
       // Удаляем элемент из массива
   }
}
Mari kita uji contoh:
Excuse excuse = new WorkExcuse();
System.out.println(excuse.generateExcuse());
Kesimpulan:
Я сегодня опоздал, потому что предпраздничное настроение замедляет метаболические процессы в моем организме и приводит к подавленному состоянию и бессоннице. 
Прошу меня извинить за непрофессиональное поведение.
Sekarang mari kita bayangkan bahawa anda melancarkan perkhidmatan, mengumpulkan statistik dan menyedari bahawa majoriti pengguna perkhidmatan adalah pelajar universiti. Untuk menambah baiknya bagi keperluan kumpulan ini, anda memesan sistem penjanaan alasan daripada pembangun lain khusus untuknya. Pasukan pembangunan menjalankan penyelidikan, menyusun penilaian, menghubungkan kecerdasan buatan, menambah integrasi dengan kesesakan lalu lintas, cuaca dan sebagainya. Kini anda mempunyai perpustakaan untuk menjana alasan untuk pelajar, tetapi antara muka untuk berinteraksi dengannya berbeza - StudentExcuse:
public interface StudentExcuse {
   String generateExcuse();
   void dislikeExcuse(String excuse);
}
Antara muka mempunyai dua kaedah: generateExcuse, yang menjana alasan, dan dislikeExcuse, yang menyekat alasan supaya ia tidak muncul pada masa hadapan. Pustaka pihak ketiga ditutup untuk pengeditan - anda tidak boleh menukar kod sumbernya. Akibatnya, dalam sistem anda terdapat dua kelas yang melaksanakan antara muka Excuse, dan perpustakaan dengan kelas SuperStudentExcuseyang melaksanakan antara muka StudentExcuse:
public class SuperStudentExcuse implements StudentExcuse {
   @Override
   public String generateExcuse() {
       // Логика нового функционала
       return "Невероятная отговорка, адаптированная под текущее состояние погоды, пробки or сбои в расписании общественного транспорта.";
   }

   @Override
   public void dislikeExcuse(String excuse) {
       // Добавляет причину в черный список
   }
}
Kod tidak boleh diubah. Skim semasa akan kelihatan seperti ini: Apakah masalah yang diselesaikan oleh Penyesuai - 2 corak reka bentuk?Versi sistem ini hanya berfungsi dengan antara muka Excuse. Anda tidak boleh menulis semula kod: dalam aplikasi yang besar, perubahan sedemikian boleh mengambil masa yang lama atau memecahkan logik aplikasi. Anda boleh mencadangkan memperkenalkan antara muka utama dan meningkatkan hierarki: Apakah masalah yang diselesaikan oleh corak reka bentuk Penyesuai - 3Untuk melakukan ini, anda perlu menamakan semula antara muka Excuse. Tetapi hierarki tambahan adalah tidak diingini dalam aplikasi yang serius: memperkenalkan elemen akar biasa memecahkan seni bina. Kelas perantaraan harus dilaksanakan yang akan membolehkan penggunaan fungsi baru dan lama dengan kehilangan minimum. Pendek kata, anda memerlukan penyesuai .

Cara corak Penyesuai berfungsi

Penyesuai ialah objek perantaraan yang membuat panggilan ke kaedah pada satu objek boleh difahami oleh yang lain. Mari kita laksanakan penyesuai untuk contoh kita dan panggilnya Middleware. Penyesuai kami mesti melaksanakan antara muka yang serasi dengan salah satu objek. Biarkanlah Excuse. Terima kasih kepada ini, Middlewareia boleh memanggil kaedah objek pertama. Middlewaremenerima panggilan dan menghantarnya ke objek kedua dalam format yang serasi. MiddlewareInilah pelaksanaan kaedah dengan kaedah generateExcusedan kelihatan seperti 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 появятся позже
}
Ujian (dalam kod klien):
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()); // Адаптер вызывает адаптированный метод
   }
}
Kesimpulan:
Обычная причина для работника:
Я сегодня опоздал, потому что предпраздничное настроение замедляет метаболические процессы в моем организме и приводит к подавленному состоянию и бессоннице.
Нет оправдания моему поступку. Я недостоин этой должности. Использование нового функционала с помощью адаптера
Alasan yang luar biasa, disesuaikan dengan keadaan cuaca semasa, kesesakan lalu lintas atau gangguan dalam jadual pengangkutan awam. Kaedah ini generateExcusehanya memindahkan panggilan ke objek lain, tanpa transformasi tambahan. Kaedah dislikeExcuseyang diperlukan terlebih dahulu meletakkan alasan pada senarai hitam pangkalan data. Pemprosesan data perantaraan tambahan adalah sebab mengapa corak Penyesuai disukai. Tetapi bagaimana pula dengan kaedah likeExcuseyang ada dalam antara muka Excuse, tetapi tidak dalam StudentExcuse? Operasi ini tidak disokong dalam fungsi baharu. Untuk kes ini, mereka mengemukakan pengecualian UnsupportedOperationException: ia dibuang jika operasi yang diminta tidak disokong. Jom guna ni. Inilah rupa pelaksanaan kelas baharu 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.
   }
}
Pada pandangan pertama, penyelesaian ini nampaknya tidak berjaya, tetapi mensimulasikan fungsi boleh membawa kepada situasi yang lebih kompleks. Jika pelanggan prihatin dan penyesuai didokumenkan dengan baik, penyelesaian ini boleh diterima.

Bila hendak menggunakan Penyesuai

  1. Jika anda perlu menggunakan kelas pihak ketiga, tetapi antara mukanya tidak serasi dengan aplikasi utama. Contoh di atas menunjukkan cara objek shim dicipta yang membungkus panggilan dalam format yang boleh difahami oleh objek sasaran.

  2. Apabila beberapa subkelas sedia ada mesti mempunyai fungsi biasa. Daripada subkelas tambahan (penciptaan mereka akan membawa kepada pertindihan kod), lebih baik menggunakan penyesuai.

Kelebihan dan kekurangan

Kelebihan: Penyesuai menyembunyikan daripada pelanggan butiran pemprosesan permintaan dari satu objek ke objek lain. Kod pelanggan tidak memikirkan tentang memformat data atau mengendalikan panggilan ke kaedah sasaran. Ia terlalu rumit, dan pengaturcara malas :) Kelemahan: Pangkalan kod projek adalah rumit oleh kelas tambahan, dan jika terdapat sejumlah besar titik tidak serasi, bilangannya boleh berkembang kepada saiz yang tidak terkawal.

Tidak boleh dikelirukan dengan Fasad dan Penghias

Selepas pemeriksaan cetek, Penyesuai boleh dikelirukan dengan corak Façade dan Penghias. Perbezaan antara Penyesuai dan Fasad ialah Fasad memperkenalkan antara muka baharu dan membungkus keseluruhan subsistem. Nah, Penghias, tidak seperti Penyesuai, menukar objek itu sendiri, bukan antara muka.

Algoritma pelaksanaan langkah demi langkah

  1. Pertama, pastikan terdapat masalah yang boleh diselesaikan oleh corak ini.

  2. Tentukan antara muka klien bagi pihak kelas lain yang akan digunakan.

  3. Laksanakan kelas penyesuai berdasarkan antara muka yang ditakrifkan dalam langkah sebelumnya.

  4. Dalam kelas penyesuai, buat medan yang menyimpan rujukan kepada objek. Rujukan ini diluluskan dalam pembina.

  5. Laksanakan semua kaedah antara muka klien dalam penyesuai. Kaedah boleh:

    • Pindahkan panggilan tanpa pengubahsuaian;

    • Tukar data, tambah/kurangkan bilangan panggilan ke kaedah sasaran, kembangkan lagi komposisi data, dsb.

    • Sebagai pilihan terakhir, jika kaedah tertentu tidak serasi, buang UnsupportedOperationException, yang perlu didokumenkan dengan ketat.

  6. Jika aplikasi menggunakan penyesuai hanya melalui antara muka klien (seperti dalam contoh di atas), ini akan membolehkan penyesuai dilanjutkan tanpa rasa sakit pada masa hadapan.

Sudah tentu, corak reka bentuk bukanlah ubat penawar untuk semua penyakit, tetapi dengan bantuannya anda boleh menyelesaikan masalah ketidakserasian objek dengan antara muka yang berbeza secara elegan. Pembangun yang mengetahui corak asas adalah beberapa langkah di atas mereka yang hanya tahu cara menulis algoritma, kerana mereka diperlukan untuk mencipta aplikasi yang serius. Menggunakan semula kod menjadi kurang sukar dan mengekalkan adalah satu keseronokan. Itu sahaja untuk hari ini! Tetapi kami tidak lama lagi akan meneruskan perkenalan kami dengan corak reka bentuk yang berbeza :)
Komen
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION