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 ?

Community
  • 1
  • 1
tadpole
  • 31
  • 1
  • 2

4 Answers4

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.

Gabe
  • 84,912
  • 12
  • 139
  • 238
Andreas Dolk
  • 113,398
  • 19
  • 180
  • 268
  • 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. – tadpole Sep 02 '10 at 21:28
  • 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 Sep 03 '10 at 00:59
  • @emory - K.I.S.S. - I just tried to code a very simple 'translation' of the given example in the question. – Andreas Dolk Sep 03 '10 at 04:29
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();
    }
}
Mike
  • 19,267
  • 11
  • 56
  • 72
  • 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 Sep 02 '10 at 21:32
  • @tadpole, I feel like the enum is one of Java's most powerful features. :) – Mike Sep 02 '10 at 21:36
  • 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 ? – tadpole Sep 03 '10 at 14:21
  • 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. – Mike Sep 03 '10 at 15:18
  • 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. – tadpole Sep 03 '10 at 15:39
5

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

gpeche
  • 21,974
  • 5
  • 38
  • 51
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.

Community
  • 1
  • 1
Emil
  • 13,577
  • 18
  • 69
  • 108