JavaRush /Java блогу /Random-KY /Көз карандылыкты киргизүүнүн оңой жолу

Көз карандылыкты киргизүүнүн оңой жолу

Группада жарыяланган
Көз карандылык инъекциясы (DI) түшүнүү оңой түшүнүк эмес жана аны жаңы же учурдагы тиркемелерге колдонуу ого бетер чаташып турат. Джесс Смит C# жана Java программалоо тилдеринде инъекциялык контейнерсиз көз карандылык инъекциясын кантип жасоону көрсөтөт. Көз карандылыкты киргизүүнүн жөнөкөй жолу - 1Бул макалада мен .NET жана Java тиркемелеринде көз карандылык инъекциясын (DI) кантип ишке ашырууну көрсөтөм. Көз карандылык инъекциясы түшүнүгү биринчи жолу иштеп чыгуучулардын көңүлүн 2000-жылы Роберт Мартин "Дизайн принциптери жана үлгүлөрү" (кийин SOLID кыскартуусу менен белгилүү болгон ) макаласын жазганда бурган. SOLIDдеги D кийинчерээк көз карандылык инъекциясы катары белгилүү болгон Инversionнын көз карандылыгына (DOI) тиешелүү. Түпнуска жана эң кеңири таралган аныктама: көз карандылыктын инversionсы – бул базалык класстын көз карандылыкты башкаруу ыкмасынын инversionсы. CopyМартиндин оригиналдуу макаласында класстын төмөнкү деңгээлдеги класска көз карандылыгын көрсөтүү үчүн төмөнкү code колдонулган WritePrinter:
void Copy()
	{
	 int c;
	 while ((c = ReadKeyboard()) != EOF)
		WritePrinter(c);
	}
Биринчи айкын көйгөй, эгерде сиз параметр тизмесин же методдун түрлөрүн өзгөртсөңүз WritePrinter, анда ал ыкмага көз карандылык бар жерде жаңыртууларды ишке ашыруу керек. Бул процесс техникалык тейлөөгө кеткен чыгымдарды көбөйтөт жана жаңы каталардын потенциалдуу булагы болуп саналат.
Java жөнүндө окууга кызыгасызбы? Java Developer тобуна кошулуңуз !
Дагы бир көйгөй: Көчүрмө классы кайра колдонуу үчүн потенциалдуу талапкер болбой калды. Мисалы, клавиатурадан киргизилген символдорду принтерге эмес, файлга чыгаруу керек болсочы? Бул үчүн классты Copyтөмөнкүдөй өзгөртө аласыз (C++ тorнин синтаксиси):
void Copy(outputDevice dev)
	{
	int c;
	while ((c = ReadKeyboard()) != EOF)
		if (dev == printer)
			WritePrinter(c);
		else
			WriteDisk(c);
	}
Жаңы көз карандылык киргизилгенине карабастан WriteDisk, кырдаал жакшырган жок (тескерисинче начарлап кетти), анткени дагы бир принцип бузулду: “программалык камсыздоо an objectилери, башкача айтканда класстар, модулдар, функциялар жана башкалар кеңейтүү үчүн ачык болушу керек, бирок алар үчүн жабык болушу керек. өзгөртүү." Мартин бул жаңы шарттуу if/else билдирүүлөрү codeдун туруктуулугун жана ийкемдүүлүгүн азайтат деп түшүндүрөт. Чечим көз карандылыктарды инversionлоо болуп саналат, ошондуктан жазуу жана окуу ыкмалары Copy. Көз карандылыктын "поп" ордуна, алар конструктор аркылуу өткөрүлөт. Өзгөртүлгөн code төмөнкүдөй көрүнөт:
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);
	}
Эми классты Copyкласстык методдордун Readerжана Writer. Класста Copyтиптердин ички түзүмү жөнүндө эч кандай маалымат жок Reader, Writerбул аларды ар кандай ишке ашыруулар менен кайра колдонууга мүмкүндүк берет. Бирок, мунун баары сизге кандайдыр бир gobbledygook сыяктуу көрүнсө, балким, Java жана C# тилдериндеги төмөнкү мисалдар кырдаалды түшүндүрөт.

Java жана C# тилдериндеги мисал

DIКөз карандылык контейнери жок көз карандылык инъекциясынын оңойлугун көрсөтүү үчүн, келгиле , бир нече кадам менен колдонууга ылайыкташтырылган жөнөкөй мисалдан баштайлы . Бизде класс бар дейли HtmlUserPresentation, анын методдору чакырылганда HTML колдонуучу интерфейсин жаратат. Бул жерде жөнөкөй мисал:
HtmlUserPresentation htmlUserPresentation = new HtmlUserPresentation();
String table = htmlUserPresentation.createTable(rowTableVals, "Login Error Status");
Бул класстын codeун колдонгон ар бир долбоор класска көз каранды болот HtmlUserPresentation, натыйжада жогоруда сүрөттөлгөн колдонууга жана тейлөөгө жөндөмдүүлүк маселелери пайда болот. Жакшыртуу дароо эле өзүн сунуштайт: класста жеткorктүү болгон бардык ыкмалардын кол тамгалары менен интерфейс түзүү HtmlUserPresentation. Бул интерфейстин мисалы:
public interface IHtmlUserPresentation {
	String createTable(ArrayList rowVals, String caption);
	String createTableRow(String tableCol);
	// Оставшиеся сигнатуры
}
Интерфейс түзүлгөндөн кийин HtmlUserPresentationаны колдонуу үчүн классты өзгөртөбүз. Типти баштоого кайрылып HtmlUserPresentation, биз эми базалык типтин ордуна интерфейс түрүн колдоно алабыз:
IHtmlUserPresentation htmlUserPresentation = new HtmlUserPresentation();
String table = htmlUserPresentation.createTable(rowTableVals, "Login Error Status");
Интерфейс түзүү бизге башка ишке ашырууларды оңой колдонууга мүмкүндүк берет IHtmlUserPresentation. Мисалы, эгер биз бул түрдү сынагыбыз келсе, анда биз базалык түрдү HtmlUserPresentationбашка түргө алмаштыра алабыз HtmlUserPresentationTest. Буга чейин киргизилген өзгөртүүлөр codeду текшерүүнү, тейлөөнү жана масштабын жеңилдетет, бирок кайра колдонуу үчүн эч нерсе жасаbyte, анткени HtmlUserPresentationтүрүн колдонгон бардык класстар анын бар экенин дагы эле бorшет. Бул түздөн-түз көз карандылыкты алып салуу үчүн, сиз интерфейстин түрүн IHtmlUserPresentationаны колдоно турган класстын же методдун конструкторуна (же метод параметрлеринин тизмесине) өткөрүп берсеңиз болот:
public UploadFile(IHtmlUserPresentation htmlUserPresentation)
Конструктор UploadFileэми типтеги бардык функцияларга жетүү мүмкүнчүлүгүнө ээ IHtmlUserPresentation, бирок бул интерфейсти ишке ашырган класстын ички түзүмү жөнүндө эч нерсе билбейт. Бул контекстте типти киргизүү класстын үлгүсү түзүлгөндө пайда болот UploadFile. Интерфейс түрү IHtmlUserPresentationар кандай ишке ашырууларды ар кандай класстарга же башка функцияларды талап кылган методдорго өткөрүү менен кайра колдонууга болот.

Корутунду жана материалды консолидациялоо боюнча сунуштар

Сиз көз карандылык инъекциясы жөнүндө билдиңиз жана класстар бири-бирине түздөн-түз көз каранды деп айтылат, эгерде алардын бири экинчисин максаттуу түрдөгү функцияга жетүү үчүн ишке киргизет. Эки түрдүн ортосундагы түз көз карандылыкты ажыратуу үчүн интерфейсти түзүшүңүз керек. Интерфейс типке талап кылынган функциянын контекстине жараша ар кандай ишке ашырууларды камтуу мүмкүнчүлүгүн берет. Интерфейс түрүн класстын конструкторуна же методуна өткөрүп берүү менен, функционалдуулукка муктаж класс/усул интерфейсти ишке ашыруучу тип жөнүндө эч кандай деталдарды билбейт. Ушундан улам, интерфейстин түрү окшош, бирок бирдей эмес жүрүм-турумду талап кылган ар кандай класстарда кайра колдонулушу мүмкүн.
  • Көз карандылык инъекциясын эксперимент кылуу үчүн, бир же бир нече тиркемелерден codeуңузду карап чыгып, көп колдонулган базалык типти интерфейске айландырууга аракет кылыңыз.

  • Бул жаңы интерфейс түрүн колдонуу үчүн бул базалык типти түздөн-түз түзүүчү класстарды өзгөртүңүз жана аны конструктор же аны колдоно турган класс методунун параметр тизмеси аркылуу өткөрүңүз.

  • Бул интерфейс түрүн сыноо үчүн сыноо ишке ашырууну түзүңүз. Кодуңуз рефакторациялангандан кийин, DIаны ишке ашыруу оңой болуп калат жана колдонмоңуз кайра колдонуу жана тейлөө жагынан канчалык ийкемдүү болуп калганын байкайсыз.
Комментарийлер
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION