سؤال

أنا لا أريد لمناقشة مزايا هذا النهج ، فقط إذا كان ذلك ممكنا.أعتقد أن الإجابة "لا".ولكن ربما شخص ما سيكون مفاجأة لي!

تخيل أن لديك مجموعة أساسية الدرجة القطعة.لديه طريقة calculateHeight(), أن يعود الارتفاع.ارتفاع كبير جدا - هذه النتيجة في أزرار (أقول) التي هي كبيرة جدا.يمكنك توسيع DefaultWidget لخلق الخاصة بك NiceWidget ، وتنفيذ الخاصة بك calculateHeight() للعودة أجمل الحجم.

الآن مكتبة فئة WindowDisplayFactory, instantiates DefaultWidget في بطريقة معقدة إلى حد ما.كنت أود أن استخدام NiceWidget.المصنع الدرجة طريقة تبدو شيئا مثل هذا:

public IWidget createView(Component parent) {
    DefaultWidget widget = new DefaultWidget(CONSTS.BLUE, CONSTS.SIZE_STUPIDLY);

    // bunch of ifs ...
    SomeOtherWidget bla = new SomeOtherWidget(widget);
    SomeResultWidget result = new SomeResultWidget(parent);
    SomeListener listener = new SomeListener(parent, widget, flags);

    // more widget creation and voodoo here

    return result;
}

أن الصفقة.نتيجة لديه DefaultWidget عميقة داخل التسلسل الهرمي من الكائنات الأخرى.السؤال - كيفية الحصول على هذا المصنع طريقة استخدام بلدي NiceWidget?أو على الأقل الحصول على بلدي calculateHeight() في هناك.من الناحية المثالية, أود أن تكون قادرة على القرد التصحيح DefaultWidget بحيث calculateHeight فعلت الصواب...

public class MyWindowDisplayFactory {
    public IWidget createView(Component parent) {
        DefaultWidget.class.setMethod("calculateHeight", myCalculateHeight);
        return super.createView(parent);
    }
}

وهو ما يمكن أن تفعله في Python, Ruby, الخ.لقد اخترع اسم setMethod() على الرغم من.الخيارات الأخرى مفتوحة بالنسبة لي هي:

  • نسخ ولصق رمز createView() طريقة في بلدي فئة يرث من المصنع الدرجة
  • الذين يعيشون مع الحاجيات التي هي كبيرة جدا

مصنع فئة لا يمكن تغييره - هو جزء من جوهر منصة API.حاولت التفكير في النتائج التي تم إرجاعها إلى الحصول على القطعة التي (في نهاية المطاف) حصلت وأضاف وإنما هو عدة القطعة-طبقات أسفل في مكان يعتاد على تهيئة الأشياء الأخرى ، مما تسبب الغريب آثار جانبية.

أي أفكار ؟ حل بلدي حتى الآن هو نسخ ولصق وظيفة ، ولكن شرطي أن يتطلب تتبع التغييرات في الأصل مصنع الدرجة عند الترقية إلى الإصدارات الأحدث من منصة, و سأكون مهتما لسماع خيارات أخرى.

هل كانت مفيدة؟

المحلول

ربما يمكنك استخدام الجانب البرمجة الموجهة إلى فخ المكالمات إلى أن وظيفة والعودة النسخة الخاصة بك بدلا من ذلك ؟

الربيع يقدم بعض اوب وظائف ولكن هناك مكتبات أخرى أن تفعل ذلك أيضا.

نصائح أخرى

واحد قبيح حل هو وضع الخاص بك تنفيذ DefaultWidget (مع نفسه FQCN) في وقت سابق على Classpath من الطبيعي التنفيذ.انها رهيبة الإختراق, ولكن كل النهج الذي يمكنني التفكير به هو أسوأ من ذلك.

مجرد مفهوم الفكرة ،

فمن الممكن أن تستخدم اوب ، مع بايت كود الهندسة طريقة حقن الجانب calculateHeight الأسلوب.

ثم قد تتيح لك التصحيح من قبل ThreadLocal أو متغير آخر.

cglib هي مكتبة جافا التي يمكن أن تفعل بعض الأشياء التي تشبه القرد الترقيع - يمكن التلاعب بايت كود في وقت التشغيل إلى تغيير بعض السلوكيات.أنا لست متأكدا مما إذا كان يمكن أن تفعل بالضبط ما تحتاج إليه ، ولكن الامر يستحق نظرة...

فمن الممكن تماما أن monkeypatch في جافا باستخدام غير آمنة.putObject وفئة الباحث.كتب بلوق وظيفة هنا:

https://tersesystems.com/blog/2014/03/02/monkeypatching-java-classes/

وجوه المنحى طريقة للقيام بذلك سيكون لإنشاء مجمع تنفيذ IWidget ، وتفويض جميع المكالمات الفعلية القطعة إلا calculateHeight, شيء من هذا القبيل:

class MyWidget implements IWidget {
    private IWidget delegate;
    public MyWidget(IWidget d) {
        this.delegate = d;
    }
    public int calculateHeight() {
        // my implementation of calculate height
    }
    // for all other methods: {
    public Object foo(Object bar) {
        return delegate.foo(bar);
    }
}

لهذا العمل تحتاج إلى اعتراض كل إبداعات القطعة التي تريد استبدالها ، مما يعني خلق مماثل المجمع عن WidgetFactory.و يجب أن تكون قادرة على تكوين أي WidgetFactory للاستخدام.

ذلك يعتمد أيضا على أي عميل يحاول أن يلقي IWidget إلى DefaultWidget...

فقط اقتراحات أستطيع أن أفكر:

  1. حفر من خلال مكتبة API لمعرفة ما إذا كان هناك طريقة تجاوز التخلف و التحجيم.التحجيم يمكن أن يكون مربكا في البديل (على الأقل بالنسبة لي) ، setMinimum, setMaximum, setdefault, setDefaultOnThursday, ....من الممكن أن يكون هناك وسيلة.إذا كان يمكنك الاتصال مكتبة المصمم(s) قد تجد جوابا التي من شأنها التخفيف من الحاجة إلى سارة القرصنة.

  2. ربما تمتد المصنع فقط تجاوز بعض الافتراضي التحجيم المعلمة ؟ يعتمد على المصنع ، ولكن قد يكون من الممكن.

إنشاء فئة مع نفس الاسم قد يكون الخيار الوحيد ، كما أشار آخرون انها قبيحة و أنت مسؤولة أن ننسى ذلك و كسر الاشياء عند تحديث مكتبة api أو نشر في بيئة مختلفة وننسى لماذا كان classpath إعداد هذا الطريق.

يمكنك محاولة استخدام أدوات مثل PowerMock/Mockito.إذا كنت يمكن أن تسخر في الاختبارات ، يمكنك أن تسخر في الإنتاج أيضا.

إلا أن هذه الأدوات ليست حقا مصممة ليتم استخدامها بهذه الطريقة سيكون لديك لإعداد البيئة نفسك و لن تكون قادرا على استخدام JUnit العدائين مثلك في الاختبارات...

حسنا, أنا أحاول بعد اقتراحات ، ثم أرى أنها لا تعمل أو التي سبق ذكرها حاولت لهم.

أفضل حل أستطيع أن أفكر من هو فئة فرعية WindowDisplayFactory ، ثم في فرعية هي createView() أسلوب النداء الأول فائقة.createView () ، ثم تعديل الكائن عاد تماما رمي القطعة واستبدالها مثيل فرعية في أن يفعل ما تريد.ولكن القطعة المستخدمة في تهيئة ذلك ، لذا عليك أن تذهب كل تلك.

ثم أفكر باستخدام التفكير في إرجاع كائن من createView() ومحاولة إصلاح الأمور بهذه الطريقة, ولكن مرة أخرى, هذا شعر لأن الكثير من الأشياء تهيئة مع القطعة.وأعتقد أن محاولة استخدام هذا النهج لو كان بسيطا بما فيه الكفاية لتبرير ذلك على النسخ واللصق.

أنا أشاهد هذا بالإضافة إلى التفكير لمعرفة ما إذا كنت يمكن أن تأتي مع أي أفكار أخرى.جافا انعكاس رائع بالتأكيد, ولكن لا يمكن أن تغلب على ديناميكية التأمل رأيت متاح في لغات مثل Perl و Python.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top