English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
retrofit هو إطار عمل طلبات شبكية ذو درجة عالية من التحرير، اكتشفت هذه التقنية القوية والعملية جدًا أثناء البحث مؤخرًا، هذا المقال سيكون مقدمة لـ retrofit، ليتمتع الجميع بمعرفة: ما هي تطبيقات التمثيل الحقيقي، ما هو التمثيل الحقيقي، كيفية استخدامه، وأين تقع محدوديته؟
أمثلة تطبيق التمثيل الحقيقي
1. AOP - برمجة منحى، تحرير البرنامج
بكلمات بسيطة، عندما تريد تنفيذ عمليات مشتركة قبل وبعد بعض الطرق الداخلية للفئات، وبينما تقوم بتنفيذ عمليات شخصية داخل الطريقة - باستخدام التمثيل الحقيقي. يمكن أن يقلل من كمية الكود عند وجود كميات كبيرة من العمل، ويقوي قابلة التشغيل.
2. تخصيص بعض طرق مكتبة الطرف الثالث
أستخدمت مكتبة خارجية ثالثة، ولكن بعض طرقها لا تتناسب مع احتياجاتي، وأريد إعادة كتابة هذه الطرق أو إضافة بعض العمليات الخاصة قبل وبعد هذه الطرق - باستخدام التمثيل الحقيقي. ولكن يجب الانتباه إلى أن لهذه الطرق محدودية، وسأوضح ذلك لاحقًا.
ما هو تمثيل ديناميكي
الرسومات أعلاه كانت مجرد تعقيد، لذا سنبدأ من أمثلة من الحياة اليومية.
إذا كنت مالكًا كبيرًا (المتمثل)، ولديك العديد من المنازل التي تريد تأجيرها، وكنت تعتقد أن التعامل مع المستأجرين معقدة، وأنك لا تريد التعامل معهم بنفسك، فإنك تبحث عن شخص لتمثيلك (المندوب) لمساعدتك في إدارة هذه الأشياء، ويطلب هذا الشخص (المندوب وهو وسيط) منك بعض الرسوم الوسيطة (عمليات إضافية لتأجير المنزل). بالنسبة للمستأجر، فإن الوسيط هو المالك، ويقوم بتمثيلك في بعض الأمور.
إلى هنا، هذا مثال على تمثيل، ولكن لماذا يسمى "تمثيل ديناميكي"، أين تتواجد كلمة "ديناميكي"؟
يمكننا التفكير بهذا الشكل، إذا كنت تمتلك كل منزلك وتطلب من وسيط مساعدتك في إدارة هذه الأشياء، فإنك تحتاج إلى طلب وسيط جديد كل مرة تريد تأجير منزل جديد، مما يعني أنك ستحتاج إلى العديد من الوكلاء، مما يكلف تكاليف وسيط مرتفعة، يمكن اعتبار هذا "تمثيل ثابت".
لكن إذا أعطينا كل منازلنا لمندوب واحد لتمثيلنا، وكان يتم التبديل بين هويات عدة منازل، لمساعدتك في التعامل مع كل مستأجر. هذا هو عملية "تمثيل ديناميكي". واحدة من الميزات الرئيسية لتمثيل ديناميكي أنه يتم إنشاء فئة التمثيل في وقت التشغيل وليس في وقت التجميع.
نحن سنرى هذا من خلال بعض الأكواد
عمليات تأجير المنزل
/** *تحديد واجهة **/ public interface RentHouse { void rent();//房屋出租 void charge(String str);//出租费用收取 }
المالك
public class HouseOwner implements RentHouse { public void rent() { System.out.println("I want to rent my house"); } public void charge(String str) { System.out.println("You get : " + str + " RMB HouseCharge."); } }
المندوب
public class DynamicProxy implements InvocationHandler { // 这个就是我们要代理的真实对象,即房东 private Object subject; // 构造方法,给我们要代理的真实对象赋初值 public DynamicProxy(Object subject) { this.subject = subject; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // قبل ممثل الكائن الحقيقي يمكننا إضافة بعض العمليات الخاصة بنا،وسيأخذ الوسيط رسوم وساطة System.out.println("before " + method.getName() + " house"); System.out.println("Method:" + method.getName()); // إذا كانت الطريقة هي charge،فسيأخذ الوسيط 100 دولار تكلفة وساطة if (method.getName().equals("charge")) { method.invoke(subject, args); System.out.println("سأحصل على رسوم الممثل 100 RMB."); } else { // عند دعوة كائن الممثل للطريقة الحقيقية،سيقوم تلقائيًا بالانتقال إلى طريقة invoke الممثل المرتبط method.invoke(subject, args); } // قبل ممثل الكائن الحقيقي يمكننا إضافة بعض العمليات الخاصة بنا System.out.println("after " + method.getName() + " house"); return null; } }
ضيف
public class Client { public static void main(String[] args) { // كائن حقيقي نريد ممثلته--المالك HouseOwner houseOwner = new HouseOwner(); // نريد ممثل كائن حقيقي،نرسل هذا الكائن داخل،وستتم دعوة الطريقة من خلال الكائن الحقيقي InvocationHandler handler = new DynamicProxy(houseOwner); /* * من خلال استخدام طريقة newProxyInstance في Proxy لإنشاء كائن الممثل لدينا،لنلقي نظرة على ثلاثة متغيراتها * الم 参数 handler.getClass().getClassLoader()،نحن هنا نستخدم محمول الكلاس handler لنحمي الكائن الممثل * الثانية parameter realSubject.getClass().getInterfaces()، نحن هنا نقدم واجهة للجسم التكامل الديناميكي هي واجهة الجسم الحقيقي، مما يعني أنني أريد تكامل الجسم الحقيقي، وبهذا أستطيع استدعاء هذه المجموعة من الواجهات. * الثالثة parameter handler، نحن هنا نقوم بربط هذا الجسم التكامل الديناميكي إلى جسم InvocationHandler هذا في الأعلى */ RentHouse rentHouse = (RentHouse) Proxy.newProxyInstance(handler.getClass().getClassLoader(), houseOwner .getClass().getInterfaces(), handler);// كلاس تكامل ديناميكي، وسيط System.out.println(rentHouse.getClass().getName()); rentHouse.rent(); rentHouse.charge("10000"); } }
دعنا نرى الناتج
com.sun.proxy.$Proxy0 before rent house Method:rent I want to rent my house after rent house before charge house Method:charge You get : 10000 RMB HouseCharge. I will get 100 RMB ProxyCharge. after charge house Process finished with exit code 0
يظهر في الناتج before rent house و after rent house، مما يعني أننا يمكننا إضافة عمليات في بداية ونهاية الطريقة.再看 في الناتج I will get 100 RMB ProxyCharge. يُظهر أننا يمكننا إضافة عمليات أو حتى استبدال الطريقة أو حتى منع تنفيذ الطريقة.
في البداية قد تشعر بالكثير من الشكوك عند النظر إلى الكود، دعنا نرى كيف نستخدم التكامل الديناميكي من خلال المحتويات التالية.
كيفية استخدام التكامل الديناميكي
في آلية التكامل الديناميكي لـ Java، هناك نوعان من الكلاسات والواجهات المهمة، واحدة هي InvocationHandler (واجهة) والأخرى هي Proxy (كلاس)، هذه الكلاس والواجهة هما ما نحتاجه لتحقيق التكامل الديناميكي.
كل موضوع تمثيل ديناميكي يجب أن يحقق واجهة InvocationHandler (المتوسط في الكود)، وكل موضوع تمثيلي يجب أن يكون مرتبطًا بـ handler، عندما نستدعي طريقة من خلال موضوع التمثيل، يتم تحويل استدعاء هذه الطريقة إلى دالة invoke (يتم كتابة تعزيز الطريقة هنا) من واجهة InvocationHandler.
Object invoke(Object proxy, Method method, Object[] args) throws Throwable
نرى أن هذه الدالة تأخذ ثلاثة معلمات، إذن ماذا يمثل كل معلماتها؟
Object invoke(Object proxy, Method method, Object[] args) throws Throwable //proxy: تمثل الموضوع الحقيقي الذي نتمثيله //method: تمثل دالة Method التي سنستدعيها للموضوع الحقيقي //args: تمثل المعلمات التي يتم تقديمها عند استدعاء طريقة معينة للموضوع الحقيقي
الآن دعونا نلقي نظرة على هذا النوع Proxy
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException
يهدف هذا النوع Proxy إلى إنشاء موضوع تمثيل ديناميكي، يقدم العديد من الأساليب، ولكن الأكثر استخدامًا هو دالة newProxyInstance:
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException
يهدف هذا النهج إلى الحصول على موضوع تمثيل ديناميكي، يتلقي ثلاثة معلمات، لنلقي نظرة على معنى هذه المعلمات الثلاثة
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException //loader: دالة ClassLoader، تحدد ما هو دالة ClassLoader التي ستقوم بتحميل موضوع التمثيل المولد //interfaces: دالة Interface متعددة، تمثل الأنواع التي سأقدمها للمواضيع التي أحتاج إلى التمثيل، إذا قدمت مجموعة من الأنواع لها، فإن موضوع التمثيل هذا سيزعم بأنه أتمثل هذه الأنواع (التفاضل)، وسأتمكن من استدعاء هذه الأنواع من الطرق //h:一个InvocationHandler对象,表示的是当我这个动态代理对象在调用方法的时候,会关联到哪一个InvocationHandler对象上
//h: كائن InvocationHandler، يمثل ذلك كيف سيتم ربط كائن الوكيل الديناميكي هذا بكائن InvocationHandler المحدد عند استدعاء هذا الوكيل الديناميكي
بهذه الطريقة، ومع مراعاة الكود المقدم أعلاه، يمكننا فهم كيفية استخدام الوكيل الديناميكي
عيوب الوكيل الديناميكي
من خلال استخدام الوكيل الديناميكي، يمكننا رؤية أن جميع الطرق التي يمكن تعزيزها هي التي تم تحقيقها من خلال واجهات (يمكن استخدام الطرق العامة غير المحققة من خلال وراثة الكائن المدعوم أيضًا)، ويعتمد الكود في هذا على وراثة HouseOwner من RentHouse. بينما لا يمكن للوكلاء الديناميكيين من JDK التعامل مع الطرق الخاصة!
الخاتمة
استخدام الوكيل الديناميكي ليس محصورًا فقط في هذه السيناريوهات، سيتم شرح المبادئ الداخلية في مقالات لاحقة، ولكن يقرر ميكانيزم إنشاء الوكيل المؤقت من خلال التعبير عن الترجيح أنه سيكون له تأثير على الأداء. لم يكن هذا المقال مقدمًا كجزء من مبدأ retrofit، فإنه لم يكن مفصلاً جدًا، إذا كانت هناك أي أخطاء أو نقاط ضعف، فلا تتردد في تقديم التعديلات!
هذا هو محتوى المقال الكامل، آمل أن يكون هذا المقال مفيدًا لكم في تعلمكم، وأتمنى أن تدعموا دليل التعليمات.
البيان: محتويات هذا المقال تم جمعها من الإنترنت، ويتمتع المالك الأصلي بحقوق الملكية، تم جمع المحتويات من قبل المستخدمين عبر الإنترنت بطرق متعددة، ولا يمتلك هذا الموقع حقوق الملكية، ولا يتم تعديل المحتويات بشكل إنساني، ولا يتحمل هذا الموقع أي مسؤولية قانونية ذات صلة. إذا رأيت محتوى يشتبه في انتهاك حقوق النسخ، فلا تتردد في إرسال بريد إلكتروني إلى: notice#oldtoolbag.com (عند إرسال البريد الإلكتروني، يرجى استبدال '#' ب '@') للإبلاغ، وتقديم الأدلة ذات الصلة، وسيتم حذف المحتوى المزعوم الذي يشتبه في انتهاك حقوق النسخ فورًا.