JavaRush /Java blogi /Random-UZ /Bog'liqlarni kiritishning oson yo'li

Bog'liqlarni kiritishning oson yo'li

Guruhda nashr etilgan
Dependency injection (DI) tushunish oson tushuncha emas va uni yangi yoki mavjud ilovalarga qo'llash yanada chalkash. Jess Smit sizga C# va Java dasturlash tillarida inyeksiya konteynerisiz qaramlik in'ektsiyasini qanday qilishni ko'rsatib beradi. Qaramlikni in'ektsiya qilishning oddiy usuli - 1Ushbu maqolada men sizga .NET va Java ilovalarida qaramlik inyeksiyasini (DI) qanday amalga oshirishni ko'rsataman. Bog'liqlik in'ektsiyasi tushunchasi birinchi marta 2000 yilda, Robert Martin "Dizayn tamoyillari va naqshlari" (keyinchalik SOLID qisqartmasi bilan ma'lum bo'lgan ) maqolasini yozganida ishlab chiquvchilarning e'tiboriga tushdi. SOLIDdagi D inversiyaga bog'liqlik (DOI) ga tegishli bo'lib, keyinchalik u qaramlik in'ektsiyasi deb nomlanadi. Asl va eng keng tarqalgan ta'rif: qaramlikni inversiyasi - bu asosiy sinf bog'liqliklarni boshqarish usulining inversiyasi. CopyMartinning asl maqolasida sinfning quyi darajadagi sinfga bog'liqligini ko'rsatish uchun quyidagi kod ishlatilgan WritePrinter:
void Copy()
	{
	 int c;
	 while ((c = ReadKeyboard()) != EOF)
		WritePrinter(c);
	}
Birinchi aniq muammo shundaki, agar siz parametrlar ro'yxatini yoki usul turlarini o'zgartirsangiz WritePrinter, ushbu usulga bog'liqlik mavjud bo'lgan joyda yangilanishlarni amalga oshirishingiz kerak. Bu jarayon texnik xizmat ko'rsatish xarajatlarini oshiradi va yangi xatolarning potentsial manbai hisoblanadi.
Java haqida o'qishga qiziqasizmi? Java Developer guruhiga qo'shiling !
Yana bir muammo: Copy sinfi endi qayta foydalanish uchun potentsial nomzod emas. Misol uchun, klaviaturadan kiritilgan belgilarni printerga emas, balki faylga chiqarish kerak bo'lsa-chi? Buning uchun siz sinfni Copyquyidagi tarzda o'zgartirishingiz mumkin (C++ tili sintaksisi):
void Copy(outputDevice dev)
	{
	int c;
	while ((c = ReadKeyboard()) != EOF)
		if (dev == printer)
			WritePrinter(c);
		else
			WriteDisk(c);
	}
Yangi qaramlik joriy qilinganiga qaramay WriteDisk, vaziyat yaxshilanmadi (lekin yomonlashdi), chunki yana bir tamoyil buzilgan: "dasturiy ta'minot ob'ektlari, ya'ni sinflar, modullar, funktsiyalar va boshqalar kengayishi uchun ochiq bo'lishi kerak, lekin ular uchun yopiq bo'lishi kerak. o'zgartirish." Martinning tushuntirishicha, bu yangi shartli if/else iboralari kodning barqarorligi va moslashuvchanligini pasaytiradi. Yechim, yozish va o'qish usullari ga bog'liq bo'lishi uchun bog'liqliklarni o'zgartirishdir Copy. Bog'liqliklarni "popping" o'rniga ular konstruktor orqali o'tkaziladi. O'zgartirilgan kod quyidagicha ko'rinadi:
class Reader
	{
		public:
		virtual int Read() = 0;
	};
	class Writer
	{
		public:
		virtual void Write(char) = 0;
	};
	void Copy(Reader& r, Writer& w)
	{
		int c;
		while((c=r.Read()) != EOF)
		w.Write(c);
	}
Endi sinfni turli xil sinf usullari va Copyilovalari bilan osongina qayta ishlatish mumkin . Sinfda turlarning ichki tuzilishi haqida hech qanday ma'lumot yo'q va bu ularni turli xil ilovalar bilan qayta ishlatishga imkon beradi. Ammo bularning barchasi sizga qandaydir gobbledygookdek tuyulsa, ehtimol Java va C# dagi quyidagi misollar vaziyatga oydinlik kiritadi. ReaderWriterCopyReaderWriter

Java va C# dagi misol

Bog'lik konteynerisiz bog'liqlikni kiritish qulayligini ko'rsatish uchun keling, DIbir necha qadamda foydalanish uchun moslashtirilishi mumkin bo'lgan oddiy misoldan boshlaylik. Aytaylik HtmlUserPresentation, bizda uning usullari chaqirilganda HTML foydalanuvchi interfeysini yaratadigan sinf mavjud. Mana oddiy misol:
HtmlUserPresentation htmlUserPresentation = new HtmlUserPresentation();
String table = htmlUserPresentation.createTable(rowTableVals, "Login Error Status");
Ushbu sinf kodidan foydalanadigan har qanday loyiha sinfga bog'liq bo'ladi HtmlUserPresentation, bu esa yuqorida tavsiflangan foydalanish va texnik xizmat ko'rsatish muammolariga olib keladi. Yaxshilanish darhol o'zini taklif qiladi: sinfda mavjud bo'lgan barcha usullarning imzolari bilan interfeys yaratish HtmlUserPresentation. Mana bu interfeysga misol:
public interface IHtmlUserPresentation {
	String createTable(ArrayList rowVals, String caption);
	String createTableRow(String tableCol);
	// Оставшиеся сигнатуры
}
Interfeysni yaratgandan so'ng, biz HtmlUserPresentationundan foydalanish uchun sinfni o'zgartiramiz. Turni yaratishga qaytsak HtmlUserPresentation, biz endi asosiy turdagi o'rniga interfeys turidan foydalanishimiz mumkin:
IHtmlUserPresentation htmlUserPresentation = new HtmlUserPresentation();
String table = htmlUserPresentation.createTable(rowTableVals, "Login Error Status");
Interfeys yaratish bizga boshqa ilovalardan osongina foydalanish imkonini beradi IHtmlUserPresentation. Misol uchun, agar biz ushbu turni sinab ko'rmoqchi bo'lsak, biz asosiy turni osongina HtmlUserPresentationboshqa turdagi bilan almashtira olamiz HtmlUserPresentationTest. Hozirgacha kiritilgan o'zgartirishlar kodni sinab ko'rish, saqlash va o'lchashni osonlashtiradi, lekin qayta foydalanish uchun hech narsa qilmaydi, chunki HtmlUserPresentationbu turdagi barcha sinflar hali ham uning mavjudligidan xabardor. IHtmlUserPresentationUshbu to'g'ridan-to'g'ri bog'liqlikni olib tashlash uchun siz undan foydalanadigan sinf yoki usulning konstruktoriga (yoki usul parametrlari ro'yxatiga) interfeys turini o'tkazishingiz mumkin :
public UploadFile(IHtmlUserPresentation htmlUserPresentation)
Konstruktor UploadFileendi turdagi barcha funksiyalardan foydalanish huquqiga ega IHtmlUserPresentation, lekin bu interfeysni amalga oshiradigan sinfning ichki tuzilishi haqida hech narsa bilmaydi. Shu nuqtai nazardan, turdagi in'ektsiya sinfning namunasi yaratilganda sodir bo'ladi UploadFile. Interfeys turi IHtmlUserPresentationturli xil ilovalarni turli sinflarga yoki turli funksionallikni talab qiladigan usullarga o'tkazish orqali qayta foydalanish mumkin bo'ladi.

Xulosa va materialni birlashtirish bo'yicha tavsiyalar

Siz qaramlik in'ektsiyasi haqida bilib oldingiz va sinflar maqsadli turdagi funksiyalarga kirish uchun ulardan biri boshqasini ishga tushirganda, bir-biriga bevosita bog'liq ekani aytiladi. Ikki tur o'rtasidagi to'g'ridan-to'g'ri bog'liqlikni ajratish uchun siz interfeys yaratishingiz kerak. Interfeys talab qilinadigan funksionallik kontekstiga qarab turga turli ilovalarni kiritish imkoniyatini beradi. Interfeys turini sinf konstruktoriga yoki usuliga o'tkazish orqali funksionallikka muhtoj bo'lgan sinf/usul interfeysni amalga oshiradigan tur haqida hech qanday ma'lumotni bilmaydi. Shu sababli, interfeys turi o'xshash, ammo bir xil bo'lmagan xatti-harakatlarni talab qiladigan turli sinflarda qayta ishlatilishi mumkin.
  • Bog'liqlik in'ektsiyasi bilan tajriba o'tkazish uchun bir yoki bir nechta ilovalardagi kodingizni ko'rib chiqing va ko'p ishlatiladigan asosiy turni interfeysga aylantirib ko'ring.

  • Ushbu yangi interfeys turidan foydalanish uchun to'g'ridan-to'g'ri ushbu asosiy turni yaratadigan sinflarni o'zgartiring va uni ishlatadigan sinf usulining konstruktori yoki parametrlari ro'yxatidan o'tkazing.

  • Ushbu interfeys turini sinab ko'rish uchun sinov dasturini yarating. Kodingiz qayta tahrirlangandan so'ng, DIuni amalga oshirish osonroq bo'ladi va siz ilovangiz qayta foydalanish va texnik xizmat ko'rsatish nuqtai nazaridan qanchalik moslashuvchan bo'lishini sezasiz.
Izohlar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION