JavaRush /Java Blog /Random-TL /Anong mga problema ang nalulutas ng pattern ng disenyo ng...

Anong mga problema ang nalulutas ng pattern ng disenyo ng Adapter?

Nai-publish sa grupo
Ang pagbuo ng software ay kadalasang kumplikado sa pamamagitan ng hindi pagkakatugma sa pagitan ng mga bahagi na gumagana sa isa't isa. Halimbawa, kung kailangan mong isama ang isang bagong library sa isang lumang platform na nakasulat sa mga naunang bersyon ng Java, maaari kang makatagpo ng hindi pagkakatugma ng mga bagay, o mas tiyak, mga interface. Ano ang gagawin sa kasong ito? Isulat muli ang code? Ngunit ito ay imposible: ang pag-aaral ng sistema ay kukuha ng maraming oras o ang panloob na lohika ng trabaho ay masisira. Anong mga problema ang nalulutas ng pattern ng disenyo ng Adapter - 1Upang malutas ang problemang ito, nakabuo sila ng pattern ng Adapter, na tumutulong sa mga bagay na may mga hindi tugmang interface na gumana nang magkasama. Tingnan natin kung paano ito gamitin!

Higit pang mga detalye tungkol sa problema

Una, gayahin natin ang pag-uugali ng lumang sistema. Sabihin nating bumubuo ito ng mga dahilan para sa pagiging huli sa trabaho o paaralan. Upang gawin ito, mayroon kaming isang interface Excusena naglalaman ng mga pamamaraan generateExcuse(), likeExcuse()at dislikeExcuse().
public interface Excuse {
   String generateExcuse();
   void likeExcuse(String excuse);
   void dislikeExcuse(String excuse);
}
Ang interface na ito ay ipinatupad ng klase 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) {
       // Удаляем элемент из массива
   }
}
Subukan natin ang halimbawa:
Excuse excuse = new WorkExcuse();
System.out.println(excuse.generateExcuse());
Konklusyon:
Я сегодня опоздал, потому что предпраздничное настроение замедляет метаболические процессы в моем организме и приводит к подавленному состоянию и бессоннице. 
Прошу меня извинить за непрофессиональное поведение.
Ngayon isipin natin na inilunsad mo ang serbisyo, nangolekta ng mga istatistika at napansin na ang karamihan sa mga gumagamit ng serbisyo ay mga estudyante sa unibersidad. Upang mapabuti ito para sa mga pangangailangan ng pangkat na ito, nag-order ka ng isang excuse generation system mula sa isa pang developer na partikular para dito. Ang development team ay nagsagawa ng pananaliksik, pinagsama-sama ang mga rating, nakakonekta sa artificial intelligence, nagdagdag ng pagsasama sa mga traffic jam, lagay ng panahon, at iba pa. Ngayon ay mayroon ka nang library para sa pagbuo ng mga dahilan para sa mga mag-aaral, ngunit ang interface para sa pakikipag-ugnayan dito ay iba - StudentExcuse:
public interface StudentExcuse {
   String generateExcuse();
   void dislikeExcuse(String excuse);
}
Ang interface ay may dalawang paraan: generateExcuse, na bumubuo ng isang dahilan, at dislikeExcuse, na humaharang sa dahilan upang hindi ito lumitaw sa hinaharap. Ang isang third-party na library ay sarado para sa pag-edit - hindi mo mababago ang source code nito. Bilang resulta, sa iyong system mayroong dalawang klase na nagpapatupad ng interface Excuse, at isang library na may klase SuperStudentExcusena nagpapatupad ng interface StudentExcuse:
public class SuperStudentExcuse implements StudentExcuse {
   @Override
   public String generateExcuse() {
       // Логика нового функционала
       return "Невероятная отговорка, адаптированная под текущее состояние погоды, пробки or сбои в расписании общественного транспорта.";
   }

   @Override
   public void dislikeExcuse(String excuse) {
       // Добавляет причину в черный список
   }
}
Hindi mababago ang code. Magiging ganito ang kasalukuyang scheme: Anong mga problema ang nalulutas ng Adapter - 2 na pattern ng disenyo?Gumagana lang ang bersyon na ito ng system sa interface ng Excuse. Hindi mo maaaring isulat muli ang code: sa isang malaking application, maaaring tumagal ang mga naturang pagbabago o masira ang logic ng application. Maaari kang magmungkahi ng pagpapakilala sa pangunahing interface at pagtaas ng hierarchy: Anong mga problema ang nalulutas ng pattern ng disenyo ng Adapter - 3Upang gawin ito, kailangan mong palitan ang pangalan ng interface Excuse. Ngunit ang karagdagang hierarchy ay hindi kanais-nais sa mga seryosong aplikasyon: ang pagpapakilala ng isang karaniwang elemento ng ugat ay sumisira sa arkitektura. Dapat ipatupad ang isang intermediate na klase na magbibigay-daan sa paggamit ng bago at lumang functionality na may kaunting pagkawala. Sa madaling salita, kailangan mo ng adaptor .

Paano gumagana ang Adapter pattern

Ang adaptor ay isang intermediate na bagay na gumagawa ng mga tawag sa mga pamamaraan sa isang bagay na naiintindihan ng isa pa. Magpatupad tayo ng adaptor para sa ating halimbawa at tawagan ito Middleware. Ang aming adaptor ay dapat magpatupad ng isang interface na tugma sa isa sa mga bagay. Hayaan na Excuse. Salamat sa ito, Middlewaremaaari itong tumawag sa mga pamamaraan ng unang bagay. Middlewaretumatanggap ng mga tawag at ipinapasa ang mga ito sa pangalawang bagay sa isang katugmang format. Ito ang hitsura ng pagpapatupad ng isang pamamaraan Middlewarena may mga pamamaraan generateExcuseat 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 появятся позже
}
Pagsubok (sa client code):
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()); // Адаптер вызывает адаптированный метод
   }
}
Konklusyon:
Обычная причина для работника:
Я сегодня опоздал, потому что предпраздничное настроение замедляет метаболические процессы в моем организме и приводит к подавленному состоянию и бессоннице.
Нет оправдания моему поступку. Я недостоин этой должности. Использование нового функционала с помощью адаптера
Isang hindi kapani-paniwalang dahilan, inangkop sa kasalukuyang kalagayan ng lagay ng panahon, mga siksikan sa trapiko o pagkagambala sa mga iskedyul ng pampublikong sasakyan. Ang pamamaraan generateExcuseay inililipat lamang ang tawag sa isa pang bagay, nang walang karagdagang pagbabago. Ang pamamaraan dislikeExcuseay kinakailangan munang ilagay ang dahilan sa isang database blacklist. Karagdagang intermediate na pagpoproseso ng data ang dahilan kung bakit minamahal ang Adapter pattern. Ngunit ano ang tungkol sa isang paraan likeExcusena nasa interface Excuse, ngunit hindi sa StudentExcuse? Ang operasyong ito ay hindi suportado sa bagong pagpapagana. Para sa kasong ito, nakabuo sila ng isang pagbubukod UnsupportedOperationException: ito ay itinapon kung ang hiniling na operasyon ay hindi suportado. Gamitin natin ito. Ito ang hitsura ng bagong pagpapatupad ng klase 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.
   }
}
Sa unang sulyap, ang solusyon na ito ay hindi mukhang matagumpay, ngunit ang pagtulad sa pag-andar ay maaaring humantong sa isang mas kumplikadong sitwasyon. Kung ang kliyente ay matulungin at ang adaptor ay mahusay na dokumentado, ang solusyon na ito ay katanggap-tanggap.

Kailan gagamitin ang Adapter

  1. Kung kailangan mong gumamit ng isang third-party na klase, ngunit ang interface nito ay hindi tugma sa pangunahing application. Ipinapakita ng halimbawa sa itaas kung paano nilikha ang isang shim object na bumabalot ng mga tawag sa isang format na naiintindihan ng target na object.

  2. Kapag ang ilang mga umiiral na subclass ay dapat magkaroon ng karaniwang pag-andar. Sa halip na mga karagdagang subclass (ang kanilang paglikha ay hahantong sa pagdoble ng code), mas mahusay na gumamit ng adaptor.

Mga kalamangan at kahinaan

Advantage: Itinago ng adapter mula sa kliyente ang mga detalye ng pagproseso ng mga kahilingan mula sa isang bagay patungo sa isa pa. Hindi iniisip ng client code ang tungkol sa pag-format ng data o paghawak ng mga tawag sa target na paraan. Ito ay masyadong kumplikado, at ang mga programmer ay tamad :) Disadvantage: Ang code base ng proyekto ay kumplikado ng mga karagdagang klase, at kung mayroong isang malaking bilang ng mga hindi magkatugma na mga puntos, ang kanilang bilang ay maaaring lumaki sa hindi makontrol na laki.

Hindi dapat malito sa Facade at Dekorador

Sa mababaw na pagsusuri, ang Adapter ay maaaring malito sa mga pattern ng Façade at Decorator. Ang pagkakaiba sa pagitan ng Adapter at Facade ay ang Facade ay nagpapakilala ng bagong interface at bumabalot ng buong subsystem. Buweno, ang Dekorador, hindi katulad ng Adapter, ay nagbabago sa mismong bagay, hindi ang interface.

Hakbang-hakbang na algorithm ng pagpapatupad

  1. Una, tiyaking may problemang malulutas ng pattern na ito.

  2. Tukuyin ang isang client interface sa ngalan kung saan isa pang klase ang gagamitin.

  3. Magpatupad ng klase ng adaptor batay sa interface na tinukoy sa nakaraang hakbang.

  4. Sa klase ng adaptor, gumawa ng field na nag-iimbak ng reference sa object. Ang reference na ito ay ipinasa sa constructor.

  5. Ipatupad ang lahat ng pamamaraan ng interface ng kliyente sa adaptor. Ang pamamaraan ay maaaring:

    • Ilipat ang tawag nang walang pagbabago;

    • Baguhin ang data, dagdagan/bawasan ang bilang ng mga tawag sa target na paraan, higit pang palawakin ang komposisyon ng data, atbp.

    • Bilang huling paraan, kung ang isang partikular na paraan ay hindi tugma, magtapon ng UnsupportedOperationException, na mahigpit na kailangang idokumento.

  6. Kung ang application ay gumagamit ng adaptor lamang sa pamamagitan ng client interface (tulad ng sa halimbawa sa itaas), ito ay magbibigay-daan sa mga adapter na mapalawak nang walang sakit sa hinaharap.

Siyempre, ang isang pattern ng disenyo ay hindi isang panlunas sa lahat para sa lahat ng mga sakit, ngunit sa tulong nito maaari mong eleganteng malutas ang problema ng hindi pagkakatugma ng mga bagay na may iba't ibang mga interface. Ang isang developer na nakakaalam ng mga pangunahing pattern ay ilang hakbang sa itaas ng mga simpleng marunong magsulat ng mga algorithm, dahil kailangan ang mga ito upang lumikha ng mga seryosong application. Ang muling paggamit ng code ay nagiging mas mahirap at ang pagpapanatili ay isang kasiyahan. Yan lamang para sa araw na ito! Ngunit sa lalong madaling panahon ay ipagpapatuloy namin ang aming pagkilala sa iba't ibang mga pattern ng disenyo :)
Mga komento
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION