JavaRush /בלוג Java /Random-HE /דרך קלה להחדיר תלות

דרך קלה להחדיר תלות

פורסם בקבוצה
הזרקת תלות (DI) היא מושג לא קל להבנה, והיישום שלו על יישומים חדשים או קיימים הוא אפילו יותר מבלבל. ג'ס סמית' מראה לך כיצד לבצע הזרקת תלות ללא מיכל הזרקה בשפות התכנות C# ו-Java. דרך פשוטה להזרקת תלות - 1במאמר זה, אני אראה לך כיצד ליישם הזרקת תלות (DI) ביישומי NET ו-Java. הרעיון של הזרקת תלות הגיע לתשומת לבם של מפתחים לראשונה בשנת 2000, כאשר רוברט מרטין כתב את המאמר "עקרונות עיצוב ודפוסים" (שנודע מאוחר יותר בראשי התיבות SOLID ). ה-D ב-SOLID מתייחס לתלות של היפוך (DOI), שלימים נודע בשם הזרקת תלות. ההגדרה המקורית והנפוצה ביותר: היפוך תלות הוא היפוך של האופן שבו מחלקת בסיס מנהלת תלות. המאמר המקורי של מרטין השתמש בקוד הבא כדי להמחיש את התלות של מחלקה Copyבמחלקה ברמה נמוכה יותר WritePrinter:
void Copy()
	{
	 int c;
	 while ((c = ReadKeyboard()) != EOF)
		WritePrinter(c);
	}
הבעיה הברורה הראשונה היא שאם אתה משנה את רשימת הפרמטרים או סוגי השיטה WritePrinter, אתה צריך ליישם עדכונים בכל מקום שיש תלות בשיטה זו. תהליך זה מגדיל את עלויות התחזוקה ומהווה מקור פוטנציאלי לטעויות חדשות.
מעוניין לקרוא על Java? הצטרף לקבוצת מפתחי Java !
בעיה נוספת: כיתת העתק אינה עוד מועמדת פוטנציאלית לשימוש חוזר. לדוגמה, מה אם אתה צריך פלט תווים שהוזנו מהמקלדת לקובץ במקום למדפסת? כדי לעשות זאת, אתה יכול לשנות את המחלקה Copyבאופן הבא (תחביר שפת C++):
void Copy(outputDevice dev)
	{
	int c;
	while ((c = ReadKeyboard()) != EOF)
		if (dev == printer)
			WritePrinter(c);
		else
			WriteDisk(c);
	}
למרות כניסתה של תלות חדשה WriteDisk, המצב לא השתפר (אלא הוחמר) מכיוון שהופר עיקרון אחר: "ישויות תוכנה, כלומר מחלקות, מודולים, פונקציות וכדומה, צריכות להיות פתוחות להרחבה, אך סגורות עבור שינוי." מרטין מסביר שהצהרות אם/אחרות החדשות הללו מפחיתות את היציבות והגמישות של הקוד. הפתרון הוא להפוך את התלות כך ששיטות הכתיבה והקריאה תלויות ב- Copy. במקום "לפוצץ" תלות, הן מועברות דרך הבנאי. הקוד שהשתנה נראה כך:
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, מה שמאפשר לעשות בהם שימוש חוזר עם יישומים שונים. אבל אם כל זה נראה לך כמו סוג של גובלדיגוק, אולי הדוגמאות הבאות ב-Java ו-C# יבהירו את המצב.

דוגמה ב-Java ו-C#

כדי להמחיש את קלות הזרקת התלות ללא מיכל תלות, נתחיל בדוגמה פשוטה שניתן להתאים אישית לשימוש DIבכמה שלבים בלבד. נניח שיש לנו מחלקה HtmlUserPresentationשכאשר השיטות שלה נקראות, מייצרת ממשק משתמש HTML. הנה דוגמה פשוטה:
HtmlUserPresentation htmlUserPresentation = new HtmlUserPresentation();
String table = htmlUserPresentation.createTable(rowTableVals, "Login Error Status");
לכל פרויקט המשתמש בקוד המחלקה הזה תהיה תלות במחלקה HtmlUserPresentation, וכתוצאה מכך בעיות השימושיות והתחזוקה שתוארו לעיל. שיפור מיידי מציע את עצמו: יצירת ממשק עם חתימות של כל השיטות הזמינות כיום בכיתה 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. השינויים שבוצעו עד כה הופכים את הקוד לקל יותר לבדיקה, תחזוקה וקנה מידה, אך לא עושים דבר לשימוש חוזר מכיוון שכל HtmlUserPresentationהמחלקות המשתמשות בסוג עדיין מודעות לקיומו. כדי להסיר את התלות הישירה הזו, אתה יכול להעביר סוג ממשק IHtmlUserPresentationלבנאי (או לרשימת פרמטרי המתודה) של המחלקה או המתודה שישתמשו בו:
public UploadFile(IHtmlUserPresentation htmlUserPresentation)
לבנאי UploadFileיש כעת גישה לכל הפונקציונליות של הסוג IHtmlUserPresentation, אך אינו יודע דבר על המבנה הפנימי של המחלקה המיישמת את הממשק הזה. בהקשר זה, הזרקת סוג מתרחשת כאשר נוצר מופע של המחלקה UploadFile. סוג ממשק IHtmlUserPresentationהופך לשימוש חוזר על ידי העברת יישומים שונים למחלקות או שיטות שונות הדורשות פונקציונליות שונה.

מסקנה והמלצות לאיחוד החומר

למדת על הזרקת תלות ועל כך שנאמר כי מחלקות תלויות ישירות זו בזו כאשר אחת מהן מבצעת מופע אחר כדי לקבל גישה לפונקציונליות של סוג היעד. כדי לנתק את התלות הישירה בין שני הסוגים, עליך ליצור ממשק. ממשק נותן לסוג את היכולת לכלול יישומים שונים, בהתאם להקשר של הפונקציונליות הנדרשת. על ידי העברת סוג ממשק לבנאי מחלקה או שיטה, המחלקה/שיטה שצריכה את הפונקציונליות אינה יודעת פרטים על הסוג המיישם את הממשק. בשל כך, ניתן לעשות שימוש חוזר בסוג ממשק על פני מחלקות שונות הדורשות התנהגות דומה, אך לא זהה.
  • כדי להתנסות בהזרקת תלות, בדוק את הקוד שלך מיישום אחד או יותר ונסה להמיר סוג בסיס בשימוש רב לממשק.

  • שנה את המחלקות המייצרות ישירות את סוג הבסיס הזה כדי להשתמש בסוג הממשק החדש הזה ולהעביר אותו דרך הבנאי או רשימת הפרמטרים של שיטת המחלקה שתשתמש בו.

  • צור מימוש בדיקה כדי לבדוק את סוג הממשק הזה. ברגע שהקוד שלך יעבור מחדש, DIזה יהפוך קל יותר ליישום, ותבחין עד כמה האפליקציה שלך נהייתה גמישה יותר מבחינת שימוש חוזר ותחזוקה.
הערות
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION