How to write it short in selecting one from hundreds of classes?

Hi,

I've written classes to generate quiz with similar features. I've define an abstract class, generalQuiz. Then

other classes inheritant from this abstract class. Let say, I have class1, class2, class3 to class100 inherited from the class 'generalQuiz' .

Now I have to write a program to accept a user input to determine which type of quiz to generate.

I define a list to hold all the classes as follows;

generalQuiz quiz1=new class1();

generalQuiz quiz2=new class2();

........

generalQuiz quiz100= new class100();

List quizList=new ArrayList( );

quizList.add(quiz1);

quizList.add(quiz2);

.......

quizList.add(quiz100);

If the program receive a user input, let say 11, it will call quiz11, an object of class11, to generate the

quiz. Then I have to write a long switch statement.

Is there a better way to write the program?

Best regards.

From Hoifo

[992 byte] By [hoifo] at [2007-9-30 8:59:00]
# 1

What's the switch statement for?

Instead of a List, why not have a Map when the key is the user input and the value is a reference to your GeneralQuiz (follow the Sun coding standards - make class names start with a capital letter).

Now when your user gives an input you just get the GeneralQuiz reference from the Map and call its method. No need for an ugly switch statement.

%

duffymo at 2007-7-2 20:44:49 > top of Java-index,Other Topics,Patterns & OO Design...
# 2

you can write a Factory class...but you will still have to use the Switch statement

public class QuizFactory{

public static GeneralQuiz getQuiz(int quizNumber){

switch(quizNumber){

case 1: return new Class1(); break;

case 2: return new Class2(); break;

....

case100: return new Class100(); break;

default: return null;

}

}

}

public class Demo{

public void testDemo(){

GeneralQuiz quiz = QuizFactory.getQuiz(11);

quiz.setGrade("A");

}

}

tnguyen at 2007-7-2 20:44:49 > top of Java-index,Other Topics,Patterns & OO Design...
# 3

you can also save the class info on a property file where the file number will be like "11.txt" for Class11.

then you can write the class..let use Quiz

class Quiz{

String[] question = new String[50];

public Quiz(int num){

if (!readFile(num + ".txt"));

useDefault();

}

public void readFile(filename){

try{

BufferedReader in ...

// set the local variables here

....

}

public useDefault(){

question[0] = "What's 1+1 = ?";

...

}

}

[/code]

if you keep alot of Quiz object around .. than use a Map as duffymo suggested.

tnguyen at 2007-7-2 20:44:49 > top of Java-index,Other Topics,Patterns & OO Design...
# 4
If the classes follow a pattern you could create a Factory method which uses the class loader.GeneralQuiz gq = (GeneralQuiz) Class.forName("org.myorg.Class"+qunizNumber).newInstance();
Peter-Lawrey at 2007-7-2 20:44:49 > top of Java-index,Other Topics,Patterns & OO Design...
# 5

Have you thought about re-thinking your design with only one quiz class ?

class Quiz {

//...

private int quizNumber;

//..

public Quiz(int number) {

this.quizNumber = number;

}

//...

Then you can create any number of instances and put them in a List or whatever...

Franck_Lefevre at 2007-7-2 20:44:49 > top of Java-index,Other Topics,Patterns & OO Design...
# 6

> Hi,

> I've written classes to generate quiz with similar

> features. I've define an abstract class, generalQuiz.

> Then other classes inheritant from this abstract class. Let

> say, I have class1, class2, class3 to class100

> inherited from the class 'generalQuiz' .

OK, You want handle the classes polymorphically, that's a good approach.

> Now I have to write a program to accept a user input

> to determine which type of quiz to generate.

> I define a list to hold all the classes as follows;

I would configure this using a mapping file, either a properties file or a XML file, that maps the reference to the class file. I would then use the System Class loader to implement a factory method to construct the objects into a hashmap, with quick reference as the key. (see the post below), and the quiz Object returned from the factory as the object.

This would be than the procedural approach you've adopted because you main controller class would not change you, you simple construct a new class, add it to the mapping data file and run.

> Then I have to write a long switch statement.

> Is there a better way to write the program?

No you dont, go with the polymorphism.

You want something like this, assuming the do method is method used to execute the concrete quiz.

AbstractQuiz abstractQuiz = quizList.get( id ) ;

abstractQuiz.do() ;

MartinS. at 2007-7-2 20:44:49 > top of Java-index,Other Topics,Patterns & OO Design...
# 7

>...

> > Then I have to write a long switch statement.

> > Is there a better way to write the program?

>

> No you dont, go with the polymorphism.

>

> You want something like this, assuming the do method

> is method used to execute the concrete quiz.

>

> > AbstractQuiz abstractQuiz = quizList.get( id ) ;

> abstractQuiz.do() ;

>

I'm still sceptical with the [Class1/Class2/...] approach...

What would really differenciate Class1 from Class2 ? And generally ClassX from ClassY ?...

If this is only a matter of quiz content, it shouldn't be needed to build one class for each content.

I would see one class for the quiz content, one class for the quiz management and one class for the quiz presentation.

Perhaps more classes for sub-components of quiz (questions, results for example),

but that's all i would think about.

Franck_Lefevre at 2007-7-2 20:44:49 > top of Java-index,Other Topics,Patterns & OO Design...
# 8

How about this?

import java.util.*

public abstract class AbstractFoo {

public AbstractFoo(String name) {

register(name, this);

}

private static Map registeredFooMap = new HashMap();

private static void register(String name, AbstractFoo foo) {

registeredFooMap.put(name, foo);

}

public static AbstractFoo getFoo(String name) {

return (AbstractFoo)registeredFooMap.get(name);

}

}

qqsu_azure at 2007-7-2 20:44:49 > top of Java-index,Other Topics,Patterns & OO Design...
# 9

String baseName = "com.somedomain.quiz.Quizz";

String specificClass = baseName + inputClassIdentifier;

Quizz q = (Quizz)Class.forName(specificClass).newInstance();

return q;

I've of course removed all errorchecking and other boilerplate code;

This will do away with the switch altogether at the cost of requiring maybe a bit more obscurity.

jwenting at 2007-7-2 20:44:49 > top of Java-index,Other Topics,Patterns & OO Design...
# 10
Quizz is either an abstract baseclass extended by or an interface implemented by all actual Quizzes.inputClassIdentifier would be your number.Will throw an exception if the class does not exist.
jwenting at 2007-7-2 20:44:49 > top of Java-index,Other Topics,Patterns & OO Design...