CodeGym /Java Blog /Random /Anong mga problema ang nalulutas ng pattern ng disenyo ng...
John Squirrels
Antas
San Francisco

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

Nai-publish sa grupo
Ang pag-develop ng software ay pinahihirapan ng mga hindi tugmang bahagi na kailangang magtulungan. 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 mga hindi tugmang bagay, o sa halip ay mga hindi tugmang interface. Anong mga problema ang nalulutas ng pattern ng disenyo ng adaptor?  - 1Ano ang gagawin sa kasong ito? Isulat muli ang code? Hindi namin magagawa iyon, dahil ang pag-analyze sa system ay aabutin ng maraming oras o ang panloob na lohika ng application ay malalabag. Upang malutas ang problemang ito, nilikha ang pattern ng adaptor. Tinutulungan nito ang mga bagay na may mga hindi tugmang interface na magtulungan. Tingnan natin kung paano ito gamitin!

Higit pa tungkol sa problema

Una, gagayahin natin ang pag-uugali ng lumang sistema. Ipagpalagay na ito ay bumubuo ng mga dahilan para sa pagiging huli sa trabaho o paaralan. Upang gawin ito, mayroon itong Excuseinterface na mayroong generateExcuse(), likeExcuse()at dislikeExcuse()mga pamamaraan.

public interface Excuse {
   String generateExcuse();
   void likeExcuse(String excuse);
   void dislikeExcuse(String excuse);
}
WorkExcuseIpinapatupad ng klase ang interface na ito:

public class WorkExcuse implements Excuse {
   private String[] excuses = {"in an incredible confluence of circumstances, I ran out of hot water and had to wait until sunlight, focused using a magnifying glass, heated a mug of water so that I could wash.",
   "the artificial intelligence in my alarm clock failed me, waking me up an hour earlier than normal. Because it is winter, I thought it was still nighttime and I fell back asleep. Everything after that is a bit hazy.",
   "my pre-holiday mood slows metabolic processes in my body, leading to depression and insomnia."};
   private String [] apologies = {"This will not happen again, of course. I'm very sorry.", "I apologize for my unprofessional behavior.", "There is no excuse for my actions. I am not worthy of this position."};

   @Override
   public String generateExcuse() { // Randomly select an excuse from the array
       String result = "I was late today because " + excuses[(int) Math.round(Math.random() + 1)] + "\\n" +
               apologies[(int) Math.round(Math.random() + 1)];
       return result;
   }

   @Override
   public void likeExcuse(String excuse) {
       // Duplicate the element in the array so that its chances of being chosen are higher
   }

   @Override
   public void dislikeExcuse(String excuse) {
       // Remove the item from the array
   }
}
Subukan natin ang ating halimbawa:

Excuse excuse = new WorkExcuse();
System.out.println(excuse.generateExcuse());
Output:

"I was late today because my pre-holiday mood slows metabolic processes in my body, leading to depression and insomnia.
I apologize for my unprofessional behavior.
Ngayon isipin na naglunsad ka ng isang serbisyong bumubuo ng dahilan, nakolekta ang mga istatistika, at napansin na karamihan sa iyong mga user ay mga estudyante sa unibersidad. Para mas mahusay na mapagsilbihan ang grupong ito, hiniling mo sa isa pang developer na gumawa ng system na gumagawa ng mga dahilan para sa mga estudyante sa unibersidad. Ang pangkat ng pagbuo ay nagsagawa ng pananaliksik sa merkado, nagraranggo ng mga dahilan, nag-hook up ng ilang artipisyal na katalinuhan, at isinama ang serbisyo sa mga ulat ng trapiko, mga ulat ng panahon, at iba pa. Ngayon ay mayroon ka nang library para sa pagbuo ng mga dahilan para sa mga mag-aaral sa unibersidad, ngunit mayroon itong ibang interface: StudentExcuse.

public interface StudentExcuse {
   String generateExcuse();
   void dislikeExcuse(String excuse);
}
Ang interface na ito ay may dalawang paraan: generateExcuse, na bumubuo ng isang dahilan, at dislikeExcuse, na pumipigil sa dahilan na lumitaw muli sa hinaharap. Hindi maaaring i-edit ang third-party na library, ibig sabihin, hindi mo mababago ang source code nito. Ang mayroon tayo ngayon ay isang system na may dalawang klase na nagpapatupad ng Excuseinterface, at isang library na may SuperStudentExcuseklase na nagpapatupad ng StudentExcuseinterface:

public class SuperStudentExcuse implements StudentExcuse {
   @Override
   public String generateExcuse() {
       // Logic for the new functionality
       return "An incredible excuse adapted to the current weather conditions, traffic jams, or delays in public transport schedules.";
   }

   @Override
   public void dislikeExcuse(String excuse) {
       // Adds the reason to a blacklist
   }
}
Hindi mababago ang code. Ganito ang hitsura ng kasalukuyang hierarchy ng klase: Anong mga problema ang nalulutas ng pattern ng disenyo ng adaptor?  - 2Gumagana lang ang bersyon na ito ng system sa interface ng Excuse. Hindi mo maaaring muling isulat ang code: sa isang malaking application, ang paggawa ng mga naturang pagbabago ay maaaring maging isang mahabang proseso o masira ang lohika ng application. Maaari naming ipakilala ang isang base interface at palawakin ang hierarchy: Anong mga problema ang nalulutas ng pattern ng disenyo ng adaptor?  - 3Upang gawin ito, kailangan naming palitan ang pangalan ng Excuseinterface. Ngunit ang sobrang hierarchy ay hindi kanais-nais sa mga seryosong aplikasyon: ang pagpapakilala ng isang karaniwang elemento ng ugat ay sumisira sa arkitektura. Dapat kang magpatupad ng intermediate class na magbibigay-daan sa amin na gamitin ang bago at lumang functionality na may kaunting pagkalugi. Sa madaling salita, kailangan mo ng adaptor .

Ang prinsipyo sa likod ng pattern ng adaptor

Ang adaptor ay isang intermediate na bagay na nagbibigay-daan sa mga tawag sa pamamaraan ng isang bagay na maunawaan 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 mo na Excuse. Pinapayagan nitong Middlewaretawagan ang mga pamamaraan ng unang bagay. Middlewaretumatanggap ng mga tawag at ipinapasa ang mga ito sa isang katugmang paraan sa pangalawang bagay. Narito ang Middlewarepagpapatupad kasama ang generateExcuseat dislikeExcusemga pamamaraan:

public class Middleware implements Excuse { // 1. Middleware becomes compatible with WorkExcuse objects via the Excuse interface

   private StudentExcuse superStudentExcuse;

   public Middleware(StudentExcuse excuse) { // 2. Get a reference to the object being adapted
       this.superStudentExcuse = excuse;
   }

   @Override
   public String generateExcuse() {
       return superStudentExcuse.generateExcuse(); // 3. The adapter implements an interface method
   }

    @Override
    public void dislikeExcuse(String excuse) {
        // The method first adds the excuse to the blacklist,
        // Then passes it to the dislikeExcuse method of the superStudentExcuse object.
    }
   // The likeExcuse method will appear later
}
Pagsubok (sa client code):

public class Test {
   public static void main(String[] args) {
       Excuse excuse = new WorkExcuse(); // We create objects of the classes
       StudentExcuse newExcuse = new SuperStudentExcuse(); // that must be compatible.
       System.out.println("An ordinary excuse for an employee:");
       System.out.println(excuse.generateExcuse());
       System.out.println("\n");
       Excuse adaptedStudentExcuse = new Middleware(newExcuse); // Wrap the new functionality in the adapter object
       System.out.println("Using new functionality with the adapter:");
       System.out.println(adaptedStudentExcuse.generateExcuse()); // The adapter calls the adapted method
   }
}
Output:

An ordinary excuse for an employee:
I was late today because my pre-holiday mood slows metabolic processes in my body, leading to depression and insomnia.
There is no excuse for my actions. I am not worthy of this position. Using new functionality with the adapter:
Isang hindi kapani-paniwalang dahilan na inangkop sa kasalukuyang mga kondisyon ng panahon, pagsisikip ng trapiko, o pagkaantala sa mga iskedyul ng pampublikong sasakyan. Ang generateExcusepamamaraan ay ipinapasa lamang ang tawag sa isa pang bagay, nang walang anumang karagdagang pagbabago. Ang dislikeExcusepamamaraan ay nangangailangan sa amin na i-blacklist muna ang dahilan. Ang kakayahang magsagawa ng intermediate na pagproseso ng data ay isang dahilan kung bakit gusto ng mga tao ang pattern ng adaptor. Ngunit ano ang tungkol sa likeExcusepamamaraan, na bahagi ng Excuseinterface ngunit hindi bahagi ng StudentExcuseinterface? Hindi sinusuportahan ng bagong functionality ang operasyong ito. Ang UnsupportedOperationExceptionay naimbento para sa sitwasyong ito. Ito ay itatapon kung ang hiniling na operasyon ay hindi suportado. Gamitin natin ito. Ganito ang Middlewarehitsura ng bagong pagpapatupad ng klase:

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("The likeExcuse method is not supported by the new functionality");
   }

   @Override
   public void dislikeExcuse(String excuse) {
       // The method accesses a database to fetch additional information,
       // and then passes it to the superStudentExcuse object's dislikeExcuse method.
   }
}
Sa unang sulyap, ang solusyon na ito ay mukhang hindi napakahusay, ngunit ang paggaya sa pag-andar ay maaaring makapagpalubha sa sitwasyon. Kung ang kliyente ay nagbabayad ng pansin, at ang adaptor ay mahusay na dokumentado, ang gayong solusyon ay katanggap-tanggap.

Kailan gagamit ng adaptor

  1. Kapag 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 gumawa ng adapter object na bumabalot ng mga tawag sa isang format na mauunawaan ng isang target na object.

  2. Kapag ang ilang mga umiiral na subclass ay nangangailangan ng ilang karaniwang pag-andar. Sa halip na lumikha ng mga karagdagang subclass (na 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. Kung marami kang hindi tugmang interface, ang bilang ng mga karagdagang klase ay maaaring maging hindi mapamahalaan.

Huwag malito ang isang adaptor sa isang facade o dekorador

Sa pamamagitan lamang ng isang mababaw na inspeksyon, ang isang adaptor ay maaaring malito sa facade at mga pattern ng dekorador. Ang pagkakaiba sa pagitan ng adapter at facade ay ang facade ay nagpapakilala ng bagong interface at bumabalot sa buong subsystem. At ang isang dekorador, hindi tulad ng isang adaptor, ay nagbabago sa mismong bagay kaysa sa interface.

Hakbang-hakbang na algorithm

  1. Una, siguraduhing mayroon kang problema na malulutas ng pattern na ito.

  2. Tukuyin ang interface ng kliyente na gagamitin upang hindi direktang makipag-ugnayan sa mga bagay na hindi tugma.

  3. Gawing mamanahin ng klase ng adaptor ang interface na tinukoy sa nakaraang hakbang.

  4. Sa klase ng adaptor, gumawa ng field para mag-imbak ng reference sa adaptee object. Ang reference na ito ay ipinasa sa constructor.

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

    • Ipasa ang mga tawag nang hindi gumagawa ng anumang mga pagbabago

    • Baguhin o dagdagan ang data, dagdagan/bawasan ang bilang ng mga tawag sa target na paraan, atbp.

    • Sa matinding mga kaso, kung ang isang partikular na paraan ay nananatiling hindi tugma, magtapon ng UnsupportedOperationException. Ang mga hindi suportadong operasyon ay dapat na mahigpit na nakadokumento.

  6. Kung ang application ay gumagamit lamang ng klase ng adaptor sa pamamagitan ng interface ng kliyente (tulad ng sa halimbawa sa itaas), kung gayon ang adaptor ay maaaring mapalawak nang walang sakit sa hinaharap.

Siyempre, ang pattern ng disenyo na ito ay hindi isang panlunas sa lahat para sa lahat ng mga sakit, ngunit makakatulong ito sa iyong eleganteng malutas ang problema ng hindi pagkakatugma sa pagitan ng mga bagay na may iba't ibang mga interface. Ang isang developer na nakakaalam ng mga pangunahing pattern ay ilang hakbang sa unahan ng mga taong alam lamang kung paano magsulat ng mga algorithm, dahil ang mga pattern ng disenyo ay kinakailangan upang lumikha ng mga seryosong application. Ang muling paggamit ng code ay hindi napakahirap, at nagiging kasiya-siya ang pagpapanatili. Yan lamang para sa araw na ito! Ngunit sa lalong madaling panahon ay patuloy nating malalaman ang iba't ibang mga pattern ng disenyo :)
Mga komento
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION