Kanuni ya ubadilishaji utegemezi inatekelezwa kwa kutumia. Ugeuzi wa Utegemezi

nyumbani / Kugombana

Kwa kweli, kanuni zote MANGO zimeunganishwa kwa nguvu na lengo lao kuu ni kusaidia kuunda programu ya hali ya juu na hatari. Lakini kanuni ya mwisho MANGO kweli anasimama dhidi yao. Kwanza, hebu tuangalie uundaji wa kanuni hii. Kwa hiyo, kanuni ya ubadilishaji utegemezi (Kanuni ya Ugeuzi wa Utegemezi - DIP): "Utegemezi wa vifupisho. Hakuna utegemezi wa kitu chochote maalum.. Mtaalamu mashuhuri wa ukuzaji programu, Robert Martin, pia anaangazia kanuni hiyo DIP na kuiwasilisha kwa urahisi kama matokeo ya kufuata kanuni zingine MANGO- kanuni iliyofunguliwa / iliyofungwa na kanuni ya uingizwaji ya Liskov. Kumbuka kwamba wa kwanza anasema kwamba darasa haipaswi kurekebishwa ili kufanya mabadiliko mapya, na ya pili inahusika na urithi na inachukua matumizi salama ya aina inayotokana ya aina fulani ya msingi bila kuvunja uendeshaji sahihi wa programu. Robert Martin awali alitunga kanuni hii kama ifuatavyo:

moja). Moduli za kiwango cha juu hazipaswi kutegemea moduli za kiwango cha chini. Moduli katika viwango vyote viwili lazima zitegemee vifupisho.

2). Vifupisho haipaswi kutegemea maelezo. Maelezo yanapaswa kutegemea vifupisho.

Hiyo ni, inahitajika kukuza madarasa kwa suala la vifupisho, na sio utekelezaji wao maalum. Na ukifuata kanuni OCP na LSP, basi hii ndiyo hasa tutafikia. Kwa hiyo, turudi nyuma kidogo kwenye somo. Huko, kama mfano, tulizingatia darasa bard, ambayo mwanzoni ilikuwa ngumu kwa darasa Gitaa, inayowakilisha ala mahususi ya muziki:

darasa la umma Bard ( gitaa la gitaa la kibinafsi; Bard ya umma(gitaa la gitaa) ( this.guitar = gitaa; ) uchezaji wa utupu wa umma() ( guitar.play(); ) )

darasa la umma Bard (

gitaa ya gitaa ya kibinafsi;

Bard ya umma (gitaa la gitaa)

hii. gitaa = gitaa;

mchezo wa utupu wa umma ()

gitaa. kucheza ();

Ikiwa tungetaka kuongeza usaidizi wa ala zingine za muziki kwenye darasa hili, basi tutalazimika kurekebisha darasa hili kwa njia fulani. Huu ni ukiukwaji wa wazi wa kanuni OCP. Na unaweza kuwa tayari umeona kwamba haya pia ni ukiukwaji wa kanuni DIP, kwa kuwa kwa upande wetu uondoaji wetu uligeuka kuwa unategemea maelezo. Kwa mtazamo wa upanuzi zaidi wa darasa letu, hii sio nzuri hata kidogo. Kufanya darasa letu kufikia masharti ya kanuni OCP tumeongeza kiolesura kwa mfumo chombo, ambayo ilitekeleza madarasa maalum yanayowakilisha aina fulani za vyombo vya muziki.

Faili Ala.java:

Ala ya kiolesura cha umma (cheza batili();)

Chombo cha interface ya umma (

voidplay();

Faili Gitaa.java:

gitaa la darasa linatumia Ala( @Override public void play() ( System.out.println("Cheza Gitaa!"); ) )

Ala ya zana za gitaa (

@Batilisha

mchezo wa utupu wa umma ()

Mfumo. nje. println("Cheza Gitaa!");

Faili lute.java:

darasa la umma Lute anatumia Ala( @Override public void play() ( System.out.println("Cheza Lute!"); ) )

darasa la umma Lute ala ala (

@Batilisha

mchezo wa utupu wa umma ()

Mfumo. nje. println("Cheza Lute!");

Baada ya hapo tulibadilisha darasa bard ili, ikiwa ni lazima, tuweze kuchukua nafasi ya utekelezaji na wale tunaohitaji. Hii huleta unyumbulifu wa ziada kwa mfumo unaoundwa na kupunguza mshikamano wake (tegemezi kali za tabaka kwa kila mmoja).

darasa la umma Bard ( chombo binafsi cha Ala; Bard ya umma() ( ) mchezo wa utupu wa umma() ( instrument.play(); ) Chombo cha utupu cha umma(Ala) ( hiki.cho = ala; ) )

darasa la umma Bard (

chombo cha chombo cha kibinafsi;

2 majibu

Hoja nzuri - neno ubadilishaji linashangaza kwa kiasi fulani (kwani baada ya kutumia DIP , moduli ya utegemezi ya kiwango cha chini sasa haitegemei moduli ya kiwango cha juu cha mpigaji simu: ama mpigaji simu au tegemezi sasa ameunganishwa kwa urahisi zaidi kupitia uondoaji wa ziada. )

Unaweza kuuliza kwa nini ninatumia neno "inversion". Kusema kweli, hii ni kwa sababu mbinu za kitamaduni zaidi za ukuzaji wa programu kama vile uchanganuzi na muundo uliopangwa huwa na muundo wa programu ambapo moduli za kiwango cha juu hutegemea moduli za kiwango cha chini na ambazo uondoaji hutegemea maelezo. Kwa kweli, moja ya madhumuni ya njia hizi ni kufafanua uongozi wa subroutines ambao unaelezea jinsi moduli za kiwango cha juu zinavyopiga simu kwa moduli za kiwango cha chini .... Kwa hivyo, muundo wa utegemezi wa programu iliyoelekezwa vizuri ya kitu ni. "inverted" kwa heshima na muundo wa utegemezi, ambayo kwa kawaida ni matokeo ya mbinu za kitaratibu za jadi.

Jambo moja la kuzingatia wakati wa kusoma karatasi ya Mjomba Bob kwenye DIP ni kwamba C++ haina (na wakati wa kuandika, haina) miingiliano, kwa hivyo kufikia uondoaji huu katika C++ kawaida hupatikana kupitia darasa la msingi la kawaida / safi, wakati katika Java. au C# uondoaji wa kulegeza kiunganishi kwa kawaida ni kufungulia kwa kuondoa kiolesura kutoka kwa utegemezi na kufunga moduli za kiwango cha juu kwenye kiolesura.

Hariri Ili tu kufafanua:

"Mahali pengine naona pia inaitwa utegemezi wa utegemezi"

Ugeuzaji: Geuza usimamizi wa utegemezi kutoka kwa programu hadi kontena (kama Spring).

Sindano ya Kutegemea:

Badala ya kuandika muundo wa kiwanda, vipi kuhusu kuingiza kitu moja kwa moja kwenye darasa la mteja. Kwa hivyo wacha darasa la mteja lirejelee kiolesura na tunapaswa kuwa na uwezo wa kuingiza aina halisi kwenye darasa la mteja. Kwa hili, darasa la mteja halihitaji kutumia neno kuu mpya na limetenganishwa kabisa na madarasa halisi.

Vipi kuhusu ubadilishaji wa udhibiti (IoC)?

Katika programu ya kitamaduni, mtiririko wa mantiki ya biashara hufafanuliwa na vitu vilivyowekwa kwa kila mmoja. Kwa ubadilishaji wa udhibiti, mtiririko unategemea grafu ya kitu ambayo imethibitishwa na kiunganishi na kufanywa iwezekanavyo na mwingiliano wa kitu unaofafanuliwa kupitia vifupisho. Mchakato wa kuunganisha hupatikana kupitia sindano ya utegemezi, ingawa wengine wanasema kuwa kutumia kitafuta huduma pia hutoa ubadilishaji wa udhibiti.

Ubadilishaji wa udhibiti kama mwongozo wa muundo hutumikia madhumuni yafuatayo:

  • Kuna kupunguzwa kwa utekelezaji wa kazi fulani kutoka kwa utekelezaji.
  • Kila moduli inaweza kuzingatia kile kinachokusudiwa.
  • Moduli hazileti mawazo yoyote kuhusu kile ambacho mifumo mingine hufanya, lakini zinategemea kandarasi zao.
  • Kubadilisha moduli hakuathiri moduli zingine.

Tazama kwa habari zaidi.

Sasisho la mwisho: 03/11/2016

Kanuni ya Ugeuzaji Utegemezi(Kanuni ya Ugeuzaji Utegemezi) inatumika kuunda huluki zilizounganishwa kwa urahisi ambazo ni rahisi kujaribu, kurekebisha na kusasisha. Kanuni hii inaweza kutengenezwa kama ifuatavyo:

Moduli za kiwango cha juu hazipaswi kutegemea moduli za kiwango cha chini. Zote mbili lazima zitegemee vifupisho.

Vifupisho haipaswi kutegemea maelezo. Maelezo yanapaswa kutegemea vifupisho.

Ili kuelewa kanuni, fikiria mfano ufuatao:

Kitabu cha Hatari ( Nakala ya mfuatano wa umma ( pata; weka; ) Kichapishi cha Kichapishaji cha Console ya umma ( pata; weka; ) utupu wa umma Chapisha() ( Printer.Chapisha(Nakala); ) ) darasa ConsolePrinter ( utupu wa umma Chapisha(maandishi ya kamba) ( Console.WriteLine (maandishi);))

Darasa la Kitabu, ambalo linawakilisha kitabu, hutumia darasa la ConsolePrinter kuchapisha. Inapofafanuliwa kama hii, darasa la Kitabu hutegemea darasa la ConsolePrinter. Zaidi ya hayo, tumefafanua kwa uthabiti kwamba uchapishaji wa kitabu unawezekana tu kwenye kiweko kwa kutumia darasa la ConsolePrinter. Chaguzi zingine, kwa mfano, pato kwa kichapishi, pato kwa faili, au kutumia vipengee vingine vya kiolesura cha picha - yote haya yametengwa katika kesi hii. Muhtasari wa uchapishaji wa kitabu haujatenganishwa na maelezo ya darasa la ConsolePrinter. Yote hii ni ukiukaji wa kanuni ya ubadilishaji wa utegemezi.

Sasa wacha tujaribu kuleta madarasa yetu kulingana na kanuni ya ubadilishaji wa utegemezi kwa kutenganisha vifupisho kutoka kwa utekelezaji wa kiwango cha chini:

Kiolesura cha IPrinter ( utupu Chapisha(maandishi ya kamba); ) Kitabu cha darasa ( kamba ya umma Maandishi ( pata; weka; ) Printer ya IP ya umma ( pata; weka; ) Kitabu cha umma(Printer Printer) ( this.Printer = printer; ) public void Chapisha( ) ( Printer.Print(Text); ) ) darasa ConsolePrinter: IPrinter ( public void Print(string text) ( Console.WriteLine("Chapisha hadi Console"); ) ) darasa HtmlPrinter: IPrinter ( public void Chapisha(string text) ( Console.WriteLine("Chapisha hadi html"); ) )

Sasa muhtasari wa uchapishaji wa kitabu umetenganishwa na utekelezaji madhubuti. Kama matokeo, darasa la Kitabu na darasa la ConsolePrinter hutegemea uondoaji wa IPrinter. Kwa kuongezea, sasa tunaweza pia kuunda utekelezaji wa kiwango cha chini wa uondoaji wa IPrinter na kuutumia kwa nguvu katika mpango:

Kitabu cha kitabu = Kitabu kipya (ConsolePrinter mpya ()); kitabu.Chapisha(); kitabu.Printer = new HtmlPrinter(); kitabu.Chapisha();

Ugeuzi wa utegemezi ni mojawapo ya nahau muhimu zaidi za programu. Kuna maelezo machache ya kushangaza ya nahau hii (kanuni) kwenye mtandao wa lugha ya Kirusi. Kwa hivyo niliamua kujaribu kufanya maelezo. Nitafanya mifano katika Java, kwa sasa ni rahisi kwangu, ingawa kanuni ya ubadilishaji wa utegemezi inatumika kwa lugha yoyote ya programu.

Maelezo haya yalitengenezwa kwa pamoja na Vladimir Matveev katika maandalizi ya madarasa na wanafunzi wa Java.

Nakala zingine kutoka kwa safu hii:

Wacha tuanze na ufafanuzi wa "utegemezi". Uraibu ni nini? Ikiwa nambari yako hutumia darasa fulani ndani au inaita kwa uwazi njia tuli ya darasa au kitendakazi fulani, huu ni utegemezi. Acha nieleze kwa mifano:

Chini ya darasa A ndani ya njia inayoitwa someMethod() huunda wazi kitu cha darasa B na hupata njia yake someMethodOfB()

Daraja la umma A ( batili Method() ( B b = new B(); b.someMethodOfB(); ) )

Vile vile, kwa mfano, darasa B inarejelea wazi sehemu tuli na njia za darasa la Mfumo:

Daraja la umma B ( void someMethodOfB() ( System.out.println("Hello world"); ) )

Katika hali zote ambapo darasa lolote (aina A) lenyewe huunda darasa lolote (aina B) au hufikia kwa uwazi sehemu tuli au washiriki wa darasa, hii inaitwa. moja kwa moja uraibu. Wale. muhimu: ikiwa darasa ndani yenyewe linafanya kazi ndani yake na darasa lingine, huu ni utegemezi. Ikiwa pia anaunda darasa hili ndani yake, basi hii moja kwa moja uraibu.

Ni nini kibaya na utegemezi wa moja kwa moja? Utegemezi wa moja kwa moja ni mbaya kwa sababu darasa ambalo hujitengenezea darasa lingine ndani yake "limefungwa" kwa darasa hili. Wale. ikiwa imeandikwa kwa uwazi kwamba B = mpya B (); , basi darasa A litafanya kazi kila wakati na darasa B na hakuna darasa lingine. Au ikisema System.out.println("..."); basi darasa litatoa kila wakati kwa System.out na hakuna mahali pengine popote.

Kwa madarasa madogo, utegemezi sio mbaya. Nambari kama hiyo inaweza kufanya kazi vizuri. Lakini katika hali zingine, ili darasa lako A lifanye kazi kwa ulimwengu wote katika mazingira ya madarasa tofauti, inaweza kuhitaji utekelezwaji mwingine wa madarasa - utegemezi. Wale. utahitaji, kwa mfano, si darasa B , lakini darasa jingine na interface sawa, au si System.out , lakini, kwa mfano, pato kwa logger (kwa mfano, log4j).

Utegemezi wa moja kwa moja unaweza kuonyeshwa kama hii:

Wale. unapounda darasa A katika nambari yako: A a = A mpya (); kwa kweli, sio darasa moja la A linaloundwa, lakini uongozi mzima wa madarasa tegemezi, mfano ambao uko kwenye picha hapo juu. Uongozi huu ni "ngumu": bila kubadilisha msimbo wa chanzo wa madarasa ya mtu binafsi, hakuna darasa katika uongozi linaweza kubadilishwa. Kwa hivyo, darasa A katika utekelezaji kama huo haliwezi kubadilika kwa mazingira yanayobadilika. Uwezekano mkubwa zaidi, haitawezekana kuitumia katika msimbo wowote, isipokuwa kwa moja maalum ambayo uliiandika.

Ili kutenganisha darasa A kutoka kwa vitegemezi maalum, tuma ombi sindano ya utegemezi. Sindano ya utegemezi ni nini? Badala ya kuunda darasa unalotaka kwa nambari, utegemezi hupitishwa kwa darasa A kupitia mjenzi:

Daraja la umma A (mwisho binafsi B b; umma A(B b) ( this.b = b; ) utupu wa umma FulaniMbinu() ( b.someMethodOfB(); ) )

Hiyo. darasa A sasa linapata utegemezi wake kupitia mjenzi. Sasa, ili kuunda darasa A, utahitaji kwanza kuunda darasa lake tegemezi. Katika kesi hii, ni B:

B b = B mpya (); A = A(b) mpya; a.someMethod();

Ikiwa utaratibu huo unarudiwa kwa madarasa yote, i.e. pitisha mfano wa darasa D kwa mjenzi wa darasa B , kwa mjenzi wa darasa D - utegemezi wake E na F , nk, basi utapata nambari, utegemezi wote ambao umeundwa kwa mpangilio wa nyuma:

G g = mpya G(); H h = H mpya (); F f = mpya(g,h); E e = E mpya (); D d = mpya D(e,f); B b = B mpya (d); A = A(b) mpya; a.someMethod();

Kielelezo, hii inaweza kuonyeshwa kama hii:

Ikiwa unalinganisha picha 2 - picha hapo juu na utegemezi wa moja kwa moja na picha ya pili na sindano ya utegemezi - unaweza kuona kwamba mwelekeo wa mishale umebadilika kinyume chake. Kwa sababu hii, nahau inaitwa "ugeuzi wa utegemezi". Kwa maneno mengine, ubadilishaji wa utegemezi upo katika ukweli kwamba darasa halitengenezi utegemezi peke yake, lakini hupokea katika fomu iliyoundwa katika mjenzi (au vinginevyo).

Kwa nini ubadilishaji wa utegemezi ni mzuri? Kwa ubadilishaji wa utegemezi, unaweza kuchukua nafasi ya utegemezi wote kwenye darasa bila kubadilisha nambari yake. Na hii inamaanisha kuwa darasa lako A linaweza kusanidiwa kwa urahisi kwa matumizi katika programu nyingine kuliko ile ambayo iliandikiwa hapo awali. Hiyo. Kanuni ya ubadilishaji wa utegemezi (wakati mwingine huitwa kanuni ya sindano ya utegemezi) ni muhimu katika kujenga msimbo unaonyumbulika, wa kawaida na unaoweza kutumika tena.

Ubaya wa sindano ya utegemezi pia inaonekana kwa mtazamo wa kwanza - vitu vya madarasa vilivyoundwa kwa kutumia muundo huu ni ngumu kuunda. Kwa hivyo, sindano ya utegemezi (inversion) kawaida hutumiwa kwa kushirikiana na maktaba fulani iliyoundwa kuwezesha kazi hii. Kwa mfano, mojawapo ya maktaba za Google Guice. Sentimita. .

© 2022 skudelnica.ru -- Upendo, usaliti, saikolojia, talaka, hisia, ugomvi