سؤال

أحاول استخدام نمط المصنع لإنشاء QuenttyPefActory حيث ستكون الفئات التي تم تأسيسها مثل multiplechoice ، truefalequestion وما إلى ذلك.

يبدو رمز المصنع شيئًا كهذا

class QuestionFactory {
    public enum QuestionType {
        TrueFalse,
        MultipleChoice,
        Essay
    }

public static Question createQuestion(QuestionType quesType) {
    switch (quesType) {
        case TrueFalse:
            return new TrueFalseQuestion();
        case MultipleChoice:
            return new MultipleChoiceQuestion();
        case Essay:
            return new EssayQuestion();
    }
    throw new IllegalArgumentException("Not recognized.");
}
}

هذا يعمل بشكل جيد الآن. إذا أردت إضافة نوع سؤال آخر ، فسأحتاج إلى تعديل فئة المصنع ولا أريد القيام بذلك.

كيف يمكنني إعداده بحيث يسجل كل فئة أسئلة نفسها بالمصنع بحيث عندما أضيف نوع سؤال جديد ، لا يتعين علي تغيير الكود للمصنع؟ أنا جديد قليلاً على جافا ولست متأكدًا من كيفية القيام بذلك.

تعديل

معلومة اضافية

جميع فئات الأسئلة تنفذ واجهة Iquestion. أنا أبحث عن طريقة لتنفيذ طريقة مثل

public static void registerType(QuestionType quesType, Class<IQuestion> ques)

حتى أتمكن من استدعاء هذه الطريقة من كتلة ثابتة من فصولي ، حتى عند إضافة نوع سؤال جديد ، لن أضطر إلى تغيير أو إضافة أي رمز في مصنع الأسئلة. أعلم أنه سيتعين علي تغيير التنفيذ الحالي لجعله عامًا. لست متأكدًا من أن الطريقة التي كتبتها أعلاه صحيحة من حيث الحجج الخاصة بها بشكل نحلي أم لا ولكنها تُظهر ما أريده في المفهوم.

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

المحلول

ربما يمكنك القيام بذلك باستخدام طريقة التسجيل التي عرضتها ، من خلال واجهة برمجة تطبيقات الانعكاس (ذلك Class شيء).

أنا لست بارعًا بما فيه الكفاية مع Java Reflection لكتابة إجابة أكثر فائدة ، ولكن إذا كنت تبحث عن البعض getConstructor الطريقة أو شيء من المحتمل أن تحصل عليه.

لاستدعاء هذه الطريقة ، يجب عليك فعل شيء مثل (لاحظ .class بناء الجملة):

QuestionFactory.registerType(QuestionType.TrueFalse, TrueFalseQuestion.class);

تعديل آه ، أيا كان ، لدي الوقت للتحقيق. جرب هذا:

public class QuestionFactory {
    static final Map<QuestionType, Constructor<? extends Question>> map =
        new HashMap<QuestionType, Class<? extends Question>>();

    public static void registerType(QuestionType quesType, Class<? extends Question> ques) {
        map.put(quesType, ques.getConstructor());
    }

    public static Question createQuestion(QuestionType quesType) {
        return map.get(quesType).newInstance();
    }
}

لم أقم بتجميع هذا ، لكن يجب أن يعمل ، أو على الأقل يرشدك في الاتجاه الصحيح. لكي يعمل هذا ، يجب أن يكون لدى تطبيقات الأسئلة مُنشئًا بدون حجج.

نظرًا لأنك تستخدم مصنعًا ثابتًا (ويعرف أيضًا باسم المتغيرات العالمية الموجهة للكائنات) ، يمكنك جعل الأسئلة تسجل نفسها التهيئة الثابتة.

public class TrueFalseQuestion implements Question {
    static {
        QuestionFactory.registerType(QuestionType.TrueFalse, TrueFalseQuestion.class);
    }
    // Whatever else goes here
}

نصائح أخرى

احتمال واحد:

public enum QuestionType {
    TrueFalse(TrueFalseQuestion.class),
    MultipleChoice(MultipleChoiceQuestion.class),
    Essay(EssayQuestion.class)

    private final Class<? extends Question> implementationType;
    QuestionType(Class<? extends Question> implementationType) {
       this.implementationType = implementationType;
    }

    public Question createQuestion() { 
       return implementationType.newInstance(); 
    }
}

بالطبع ، يتخلص هذا من المصنع ويفترض أن جميع أسئلتك تحتوي على مُنشئين من ARGS ، ولكن بقدر ما أستطيع أن أقول ، فإنه يغطي جميع حالات رسم الكود أعلاه. إذا كان بناء الفصول الدراسية بشكل خاص أكثر تعقيدًا ، فيمكنك دائمًا إعداد شيء مثل:

public enum QuestionType {
    TrueFalse { public Question createQuestion() { /* construction logic goes here */ } }
    public abstract Question createQuestion();
}

أنا متأكد من أنك تريد فقط إنشاء طريقة على نوع التعداد الخاص بك والذي سيعيد كائن السؤال المناسب. لذلك في أي وقت يضيف شخص ما قيمة التعداد إلى QuestionType ، سيتعين عليهم أيضًا تحديث الطريقة. لا تحل مشكلتك في الاضطرار إلى تحديث هذه الطريقة على الرغم من ...

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