
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 itongExcuse
interface na mayroong generateExcuse()
, likeExcuse()
at dislikeExcuse()
mga pamamaraan.
public interface Excuse {
String generateExcuse();
void likeExcuse(String excuse);
void dislikeExcuse(String excuse);
}
WorkExcuse
Ipinapatupad 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 Excuse
interface, at isang library na may SuperStudentExcuse
klase na nagpapatupad ng StudentExcuse
interface:
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: 

Excuse
interface. 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 itoMiddleware
. Ang aming adaptor ay dapat magpatupad ng isang interface na tugma sa isa sa mga bagay. Hayaan mo na Excuse
. Pinapayagan nitong Middleware
tawagan ang mga pamamaraan ng unang bagay. Middleware
tumatanggap ng mga tawag at ipinapasa ang mga ito sa isang katugmang paraan sa pangalawang bagay. Narito ang Middleware
pagpapatupad kasama ang generateExcuse
at dislikeExcuse
mga 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 generateExcuse
pamamaraan ay ipinapasa lamang ang tawag sa isa pang bagay, nang walang anumang karagdagang pagbabago. Ang dislikeExcuse
pamamaraan 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 likeExcuse
pamamaraan, na bahagi ng Excuse
interface ngunit hindi bahagi ng StudentExcuse
interface? Hindi sinusuportahan ng bagong functionality ang operasyong ito. Ang UnsupportedOperationException
ay naimbento para sa sitwasyong ito. Ito ay itatapon kung ang hiniling na operasyon ay hindi suportado. Gamitin natin ito. Ganito ang Middleware
hitsura 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
-
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.
-
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
-
Una, siguraduhing mayroon kang problema na malulutas ng pattern na ito.
-
Tukuyin ang interface ng kliyente na gagamitin upang hindi direktang makipag-ugnayan sa mga bagay na hindi tugma.
-
Gawing mamanahin ng klase ng adaptor ang interface na tinukoy sa nakaraang hakbang.
-
Sa klase ng adaptor, gumawa ng field para mag-imbak ng reference sa adaptee object. Ang reference na ito ay ipinasa sa constructor.
-
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.
-
-
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.
GO TO FULL VERSION