בעיה עם Java runtime type indetification - תכנות - HWzone פורומים
עבור לתוכן
  • צור חשבון

בעיה עם Java runtime type indetification


MasterDK

Recommended Posts

זו בעיה דיי ידוע ואני מחפש אליה את הפתרון הפשוט ביותר והטוב ביותר.

תיאור הבעיה:

נתונה מחלקה BasePacket שממשת את האינטרפייס Serializable.

למחלקה יש בנים כגון: LoginPacket, LoginFailPacket, PingPacket, PongPacket וכדומה (רמת ההורשה היא 1, כלומר ל BasePacket אין נכדים רק בנים).

נתונים שתי לקוחות A ו B שיש ביניהם סוקט פתוח והם מדברים בפרוטוקול מסויים ששולח את אחת ממחלקות הבנים של BasePacket (היא עצמה אבסטרקטית ולכן לא ניתן לשלוח אותה). תהליך שליחת חבילה LoginPacket מ A ל B נראה ככה:


LoginPacket login = new LoginPacket(.., .., ..);
X x = Serialize(login);
Send(x);

בואו נצא מהחנה ש Serialize עושה סריאליזציה ומחזיר אובייקט מסוג מסויים אשר ניתן לשליחה בסוקט, ו Send שולח את הבוייקט הזה.

בצד B זה נראה ככה:


while(noData()) {}
X x = Receive();
BasePacket packet = Deserialize(x);
NeededType p = ???(packet);
DoSomething(p);

מקבלים את אותו X ש A שלח, עושים לו תהליך הפוך ומקבלים BasePacket. עכשיו תלוי במידע שקיבלתי אני צריכים לעשות דברים שונים (קיבלתי לוגין צריך לודא מידע ולשלוח תשובה, קיבלתי פינג צריך לשלוח פונג וכו') הבעיה היא שאני לא יודע מה קיבלתי. אחת הדרכים זה לעשות if-else ארוך עבור כל בן של BP ולבדוק האם packet הוא מסוג לוגין אחרת האם הוא מסוג פינג אחרת האם... וכו'. דרך אחרת דיי דומה לקודמת היא להוסיף שדה ל BP שיכיל מספר ייחודי שמתאר אחד לאחד את אחד הבנים שלו ואז לעשות משהוא כזה:


if(packet.pType == PACKET_LOGIN)
doLogin((LoginPacket)packet);
else if(...)
...

ניסיתי לתאר כמה שאפשר את הבעיה ואם משהוא לא מובן אני יכול לנסות שוב.

אשמח לדעת על פתרון יפה לבעיה הנ"ל.

תודה רבה מראש!

קישור לתוכן
שתף באתרים אחרים

נחלק לשתי בעיות:

1) איך לדאוג שעבור מידע מסוג X תקבל אוביקט מסוג X בתוך B.

2) איך לדאוג שעבור כל X תתבצע הפעולה הנכונה.

אחרי שפתרת את (1) התשובה ל-(2) ברורה - פולימורפיזם, כלומר קריאה למתודה וירטואלית (ב-JAVA כל המתודות ויטואליות בברירת מחדל).

יש design pattern (ולמעשה יש משפחה שלמה) שנקראת factory (יש כל מני וריאציות). תחפש על זה.

הרעיון המרכזי: יש לך פונקציה (מתודה, לא משנה) שמקבלת נתונים ומחזירה איזשהו base class, אבל הטיפוס הקונקרטי של מה שהיא מחזירה תלוי בנתונים. כלומר הפונקציה מקבלת נתונים ומייצרת מחלקה מהטיפוס הנכון.

שיטה שתתאים לך: תייצר interface שנקרא לו נניח PacketHandler ויש לו מתודה אחת בשם HandlePacket (זה שם לא כ"כ מוצלח אבל נלך על זה) שעושה את העבודה של B עבור כל טיפוס. תממש מספר handler-ים מהטיפוסים המתאימים: PingHandler, LoginHandler וכו'.

עכשיו אתה צריך איזהו factory שמקבל את x ומחזיר PacketHandler.


HandlerFactory factory = ....;
X x = Receive();
PacketHandler handler = factory.CreateHandler(x);
handler.HandlePacket();

ונחזור לשאלה המרכזית: איך לייצר את הטיפוס הנכון בתוך ה-factory? יש מספר שיטות.

אחת היא כמו שהצעת, if-else. זה לא ממש טוב.

הבאה היא בעזרת switch. זה כבר יותר טוב, ואפילו מתאים למקרים פשוטים, אבל גם לו יש בעיות.

עוד שיטה היא בעזרת מפה: תכין מפה שממפה את הטיפוס (נניח שהוא int) ל-factory מתאים אשר יודע לייצר אובייקטים מהסוג הנכון.

הנה לך הסבר: http://en.wikipedia.org/wiki/Abstract_factory_pattern

קישור לתוכן
שתף באתרים אחרים

בהצלחה.

אפ זה מעניין אותך, אני ממליץ שתקרא קצת על design patterns. מעין סט של פתרונות ידועים לבעיות שצצות הרבה.

אני מצאתי שהספר הזה די מועיל וקריא: http://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612

קישור לתוכן
שתף באתרים אחרים

בהצלחה.

אפ זה מעניין אותך, אני ממליץ שתקרא קצת על design patterns. מעין סט של פתרונות ידועים לבעיות שצצות הרבה.

אני מצאתי שהספר הזה די מועיל וקריא: http://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612

כן תודה רבה אני מכיר את זה כבר, פשוט לא הצלחתי לשלב את אחד ה patternים לבעיה שלי (חוסר ניסיון אני מאמין).

שוב תודה!

קישור לתוכן
שתף באתרים אחרים

ארכיון

דיון זה הועבר לארכיון ולא ניתן להוסיף בו תגובות חדשות.

×
  • צור חדש...