Service Locator

18 בDecember 2012

תגיות:
2 תגובות

Service Locator Pattern

תבנית פשוטה למימוש,
שנחשבת כיום לטכניקת הנדסת תכנה פופולרית מאוד,

חלק מתבנית Dependency Injection  מציג  פתרון דומה לבעיה ולפעמים הן “מתחרות ראש
בראש” במי נבחר להשתמש.

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

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

א.   
לא נרצה ריבוי אובייקטים סטטיים במערכת.

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

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

ד.   
בלי להיכנס לנושא הIOC  ותלות שנוצרת בזמן ריצה שזה נפתר ב Dependency Injection

נוסיף על
כל זה קוד מסורבל ולא קריא.. שלא לדבר על יעיל.

אז אכן הפתרון
האולטימטיבי כבר קיים בשטח ונקרא
Service Locator. ואמור להסיר מאתנו את
האחריות ל, איפה נוצר האובייקט, מי כמה ולמה. אלא פשוט יש לנו אובייקט כללי שמחזיק
את כל הישויות ואם אני נצרך לרפרנס כלשהוא אני פונה
 ל Service
Locator
ומבקש נתונים, שירותים
וכו’.
התבנית קצת מזכירה לי הסבר שאני נותן על הצורך ב
Static Class. כולם יודעים שזה Anti Pattern

ואז סטודנטים שואלים
“אז מתי נשתמש בזה? ” תשובה טובה יכולה להיות כשיש לנו פונקציות כלליות
שלא מעניין אותי באיזה קלאס הן כתובות, כל שמעניין אותי זה הפונקציונליות שאני
מקבל מהן, ובכן אולי זה הזמן לשים ב
Static Class..(כל זה לפני שאני מכירים
Design Patterns)  וזה מחזיר אותי לService Locator. אנו רוצים מישהוא שנפנה אליו. תן לי רפרנס, תן לי שירות, תן לי
רפרנס, תן לי שירות, תן לי רפרנס, תן לי שירות, … בלי
static , בלי יצירת מופעים והגדרת תלויות..

הרווח מניצול התבנית
הוא:

הפרדת אובייקטים
מהתלויות שלהם.

זמינות בעת הצורך (ServiceLocatoe.GetService(typeOf T ) בלי ברבה עבודה.

שמירה על מבנה מופרד
לצרכי בדיקה ותכנון.

אני אציג דוגמא
בסיסית שאותה כמובן אפשר לייעל ולהרחיב.

*הערה כמובן ש אם קצת מחשבה נדאג שהאובייקטים שאותו “מרכז
שירות והפניה” יהיו
סינגלטון, ובנוסף גם במצב איתחול
עצל .
בחלק מהמקרים, ועוד
יותר מזה נסו לחשוב על פתרון גנרי כמו שאני אציג עכשיו.

 

א.  
אני מגדיר חוזה לServiceL:

public interface IServiceLocator

    {

        T GetService<T>();

        void AddService(object o);

        void RemovService(object o);

     }

                                                                                                                           

         

ב.  
מימוש לחוזה:

public class ServiceLocator : IServiceLocator

    {

        private Dictionary<Type, object> services;

    

        internal ServiceLocator()

        {

            services = new Dictionary<Type, object>();

        }

 

        public T GetService<T>()

        {

            try

            {

                return (T)services[typeof(T)];

            }

            catch (KeyNotFoundException)

            {

                throw new ApplicationException(“no such a
Service”
);

            }

        }

 

        public void AddService(object o)

        {

            services.Add(o.GetType(), o);

        }

 

        public void RemovService(object o)

        {

            Type t = o.GetType();

          

 

            if (services.ContainsKey(t))

            {

                services.Remove(t);

            }

          }

     }

             

        

   

                                                          

ג.  שירותים
שונים(…-1), (לא משנה מיהם ומה השירות, אנו מטפלים בהם לפי טיפוס גנרי):

public class BrainStatusService

    {

        public string F()

        {

          return(“you got no Brain,
sorry”
);

        }

    }

 

    public class TimeService

    {

        public string F()

        {

            return (DateTime.Now.ToShortTimeString());

        }

}   

   

ד.  איזשהו
לקוח שמעוניין בשירות מתוך רשימת השירות, (במקום ליצור תלויות מייגעות):

public class client

    {

       public ServiceLocator locator{get; set;}

        public void UseService<T>()

        {

            T res ;

            res =
locator.GetService<T>();

        }

}    

                                                                      

ה.  הרצה
לבדיקה… :

class Program

    {

        static void Main(string[] args)

        {

            client c = new client();

            ServiceLocator service = new ServiceLocator();

            c.locator = service;

            service.AddService(new BrainStatusService());

            service.AddService(new TimeService());

            string res = c.locator.GetService<BrainStatusService>().F();

            Console.WriteLine(res);

        }

}  

                                                                 

 

 

 

 

 

 
סיכום:

תבנית פשוטה ויעילה,
אנחנו יכלים על הדרך לראות בדוגמא כמה יכול להיות שימושי עבודה עם
Generics,

לא יעיל במקום שיש לי
תלויות (
Dependencies) שאני מעוניין בהם, כמו בשימוש בMVC

או בשימוש בIUnityContainer לדוגמא, אבל זאת שיטה מצוינת גם אז, להשתמש
בשירותים כלליים בפרוייקט בלי להיגרר ל
Statics, ובמינימום קוד.

הוסף תגובה
facebook linkedin twitter email

Leave a Reply

Your email address will not be published. Required fields are marked *

2 תגובות

  1. ロレックスコピー18 בDecember 2012 ב 5:00

    売れてるからって「天狗」になってる感もないから

    Reply
  2. シャネルコピー19 בDecember 2012 ב 8:12

    盛り上がってるのはメディア側だけ。

    Reply