3

Possible Duplicate:
What's the nearest substitute for a function pointer in Java?

I am writing a factory class to create a bunch of different widgets. For argument sake, suppose this factory can create 1000 widgets.

myWidget createWidget (widgetId) { case 0: createwidget0 (); . . case 1000: createwidget1000 (); } 

I don't want to write 1000 cases statement. I want to put all the creation routines in an array. Use the widgetId as an index to execute the create routine directly so it does not have to go through comparing 1000 condition. So the whole createWidget routine can be simplified like this

myWidget createWidget (widgetId) { myAwsomeFuncArr createFunc; myWidget widget = createFunc[widgetId] (); } 

Is there away to do this in Java ?

2
  • 2
    possible duplicate: stackoverflow.com/questions/122407/… Commented Sep 2, 2010 at 20:58
  • You don't even need an array, try getClass().getMethod("createwidget"+widgetId).invoke(); will replace your case/array. Commented Sep 4, 2010 at 7:57

4 Answers 4

8

Implement widget factories and store them in your big array. That would be pretty close:

public interface WidgetFactory { public Widget create(); } 

and somewhere else:

public class MyClass { private static Widgetfactory[] widgetFactories = new WidgetFactory[1000]; static { widgetFactories[0] = new FancyButtonFactory(); // FancyButtonFactory implements WidgetFactory widgetFactories[1] = new FancyTextFieldFactory(); // see above // ... } static public Widget createWidget(int index) { return widgetFactories[index].create(); } } 

This piece of code is only written to show a similiar approach without function pointers. Real life applications will use a (much) better design.

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks Andreas, this is similar to I had in mind although allocating the object in advance might pose a problem, but I think I can get around it.
Good Answer +1. I realize that this is only sample code, but I am nonetheless curious - why create a WidgetFactory class and not use java.util.concurrent.Callable? Is there a design reason to prefer one over the other?
@emory - K.I.S.S. - I just tried to code a very simple 'translation' of the given example in the question.
7

I'm a huge fan of using Java enumerations to accomplish this sort of task. A clean solution, and hey, type safety!

public abstract class Widget { protected boolean loaded; public Widget() { loaded = false; } } public class ConcreteWidgetA extends Widget { public ConcreteWidgetA() { super(); } public void doSomething() { if (!loaded) { load(); loaded = true; } } private void load() { } } public class ConcreteWidgetB extends Widget { public ConcreteWidgetB() { super(); } public void doSomethingElse() { if (!loaded) { load(); load = true; } } private void load() { } } public enum Widgets { CONCRETE_WIDGET_A(new ConcreteWidgetA()), CONCRETE_WIDGET_B(new ConcreteWidgetB()); private Widget widget; public Widgets(Widget aWidget) { widget = aWidget; } public Widget getWidget() { return widget; } } public class WidgetFactory { //Here's the money maker. public static Widget createWidget(Widgets aWidgetElement) { return aWidgetElement.getWidget(); } } 

5 Comments

This is interesting. This solution is not easily understand as the one posed by Andreas although this might be a better option. I have to study some more. Thanks.
@tadpole, I feel like the enum is one of Java's most powerful features. :)
As nice as some of these solutions are, I see an Achille heel in them. Please correct me if I am wrong. These solutions expected the objects to be created in advance. My problem is supposed the application has 100 of dialogs. Some of these dialogs can require a bunch of resources. They don't need to be created until they are needed. The allocating them in advance just waisted resources and slower startup time. Do you have any advices ?
That indeed poses a problem for the design that I posted. You're correct in that I'm pre-allocating resources. One option that comes to mind is to Lazy Load the real guts of the Widgets when they're requested. The other is to use the Flyweight pattern, though I think it might be slightly less applicable. I'll update my code to show how Lazy Load might help.
I see. The Lazy load is a good idea. I can take it from here. No need for you to spend more time. Thank you.
5

The equivalent of a function pointer in Java is a function object or functor.

Comments

1

A Sample Functor:

public class Functor { interface func{ int fun(int x,int y); String toString(); } public static void main(String[] args) { func add=new func(){ public int fun(int x, int y) { return x+y; } public String toString() { return "+"; } }; func mult=new func(){ public int fun(int x, int y) { return x*y; } public String toString() { return "*"; } }; func[] arr={add,mult}; int i[]={10,20,30,40}; for(int val:i) for(func f:arr) System.out.println(val+""+f+val+"="+f.fun(val,val)); } } 

Note:If you do something like this for 1000 widgets then you will be making 1000 anonymous class files.I don't know if it can affect the performance.So you better make sure about that before implementing.

I would rather prefer Andreas's or Mikes's solution for a situation like yours.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.