Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Java > dispatch class, modularity, initialisation?

Reply
Thread Tools

dispatch class, modularity, initialisation?

 
 
bugbear
Guest
Posts: n/a
 
      09-03-2007
I would like to have a base class
"Widget", that amongst other things
has a method getWidgetFor(String name).

I would like this method to be able to use (e.g.)
a Widget class static HashMap to look up Widgets.

Each entry in the Map will be an instance
of a sub-class of widget; some sub-classes
may "want" to put more than one entry in the map.

So - how do I populate the map?

If I have a static block in each sub-class,
I have no trivial way of ensuring
that ALL my subclasses have been referred
to (thus loading them, and running any static
code blocks).

If I have an "init()" method in each sub-class,
it might be called more than once.

I welcome advice, tip, examples, opinions etc.

BugBear
 
Reply With Quote
 
 
 
 
Ingo R. Homann
Guest
Posts: n/a
 
      09-03-2007
Hi,

sounds like some kind of Plugin-Mechanism?

In fact, since you cannot make sure that all subclasses are loaded, you
also cannot make sure that all static initializers are called (I think
you have realized that problem already), and of course you cannot make
sure that the init-methods of all classes are called (same problem)! (Of
course it would be no problem to secure that they are not called twice
by using a flag.)

You say, you need a mapping from "widget name" to "widget class". You do
not say if you need a list of all available widgets. If you do not need
such list, a quite easy solution would be to locate the widget classes
in a certain package and - e.g. if the widget is called "Foo", call the
class "myWidgetPackage.FooWidget". Then you can easily map the name to a
class just by calling Class.forName()!

However, if you need a list of all widgets, you will either have to
manually list them in a property file or e.g. locate them in a certain
directory and scan this directory at startup.

Ciao,
Ingo




bugbear wrote:
> I would like to have a base class
> "Widget", that amongst other things
> has a method getWidgetFor(String name).
>
> I would like this method to be able to use (e.g.)
> a Widget class static HashMap to look up Widgets.
>
> Each entry in the Map will be an instance
> of a sub-class of widget; some sub-classes
> may "want" to put more than one entry in the map.
>
> So - how do I populate the map?
>
> If I have a static block in each sub-class,
> I have no trivial way of ensuring
> that ALL my subclasses have been referred
> to (thus loading them, and running any static
> code blocks).
>
> If I have an "init()" method in each sub-class,
> it might be called more than once.
>
> I welcome advice, tip, examples, opinions etc.
>
> BugBear


 
Reply With Quote
 
 
 
 
SadRed
Guest
Posts: n/a
 
      09-03-2007
On Sep 3, 6:44 pm, bugbear <bugbear@trim_papermule.co.uk_trim> wrote:
> I would like to have a base class
> "Widget", that amongst other things
> has a method getWidgetFor(String name).
>
> I would like this method to be able to use (e.g.)
> a Widget class static HashMap to look up Widgets.
>
> Each entry in the Map will be an instance
> of a sub-class of widget; some sub-classes
> may "want" to put more than one entry in the map.
>
> So - how do I populate the map?
>
> If I have a static block in each sub-class,
> I have no trivial way of ensuring
> that ALL my subclasses have been referred
> to (thus loading them, and running any static
> code blocks).
>
> If I have an "init()" method in each sub-class,
> it might be called more than once.
>
> I welcome advice, tip, examples, opinions etc.
>
> BugBear


As the value of the Map, use Collection<Entry> instead of a bare Entry
object.

 
Reply With Quote
 
bugbear
Guest
Posts: n/a
 
      09-03-2007
SadRed wrote:
> On Sep 3, 6:44 pm, bugbear <bugbear@trim_papermule.co.uk_trim> wrote:
>> I would like to have a base class
>> "Widget", that amongst other things
>> has a method getWidgetFor(String name).
>>
>> I would like this method to be able to use (e.g.)
>> a Widget class static HashMap to look up Widgets.
>>
>> Each entry in the Map will be an instance
>> of a sub-class of widget; some sub-classes
>> may "want" to put more than one entry in the map.
>>
>> So - how do I populate the map?
>>
>> If I have a static block in each sub-class,
>> I have no trivial way of ensuring
>> that ALL my subclasses have been referred
>> to (thus loading them, and running any static
>> code blocks).
>>
>> If I have an "init()" method in each sub-class,
>> it might be called more than once.
>>
>> I welcome advice, tip, examples, opinions etc.
>>
>> BugBear

>
> As the value of the Map, use Collection<Entry> instead of a bare Entry
> object.
>


I don't understand what part of my problem this helps;
please expand?

BugBear
 
Reply With Quote
 
Lew
Guest
Posts: n/a
 
      09-03-2007
bugbear wrote:
>>> I would like to have a base class
>>> "Widget", that amongst other things
>>> has a method getWidgetFor(String name).
>>>
>>> I would like this method to be able to use (e.g.)
>>> a Widget class static HashMap to look up Widgets.
>>>
>>> Each entry in the Map will be an instance
>>> of a sub-class of widget; some sub-classes
>>> may "want" to put more than one entry in the map.


By this, do you mean that a subclass may want to add more than one key, each
with its own value?

>>> So - how do I populate the map?


Have each class register itself with the parent class's registry as part of
its static initializer.

public class Sub extends Widget
{
static
{
synchronized ( Widget.registry )
{
registry.put( aKey, someValue );
registry.put( bKey, otherValue );
...
}
}
}

Obviously all get()s from the registry must be synchronized on the registry, too.

>>> If I have a static block in each sub-class,
>>> I have no trivial way of ensuring
>>> that ALL my subclasses have been referred
>>> to (thus loading them, and running any static
>>> code blocks).


Nope. Just the ones that have initialized.

One cannot, in general, determine all subclasses from the parent class,
because new subclasses can be loaded at any moment, including /just/ after
taking inventory.

OTOH, each subclass knows of its own existence as it's born, thus can register
itself as part of its initialization. Thus, while you cannot determine /a
priori/ that each subclass has been registered, each subclass can guarantee
that it will not be used until it's registered.

>>> If I have an "init()" method in each sub-class,
>>> it might be called more than once.


Not if you code it right, make it no more visible than package-private, and
use a factory method instead of a constructor.

SadRed wrote:
>> As the value of the Map, use Collection<Entry> instead of a bare Entry
>> object.


bugbear wrote:
> I don't understand what part of my problem this helps;
> please expand?


It's a bad idea to keep a collection of Map.Entry as a value, if that's what
was meant by the advice. It might be a good idea to keep a Collection<V> or
Collection<? extends V> where V is the type of your values.

I think SadRed is solving your problem of subclasses registering more than one
entry, on the reading that you wanted to keep more than one value per key, but
I'm not sure that's what was meant. I do know that I had to read the original
post to see if that's what you wanted, or if you wanted to keep several values
per subclass that have different keys.

One also wonders how you prevent key collisions between subclasses. Perhaps
you need a key that is a Pair< Class<? extends Widget>, ? extends KeyType > as
the key to your map. Thus each subclass entry is keyed by its own class and
its own key values,

--
Lew
 
Reply With Quote
 
bugbear
Guest
Posts: n/a
 
      09-03-2007
Lew wrote:
> bugbear wrote:
>>>> I would like to have a base class
>>>> "Widget", that amongst other things
>>>> has a method getWidgetFor(String name).
>>>>
>>>> I would like this method to be able to use (e.g.)
>>>> a Widget class static HashMap to look up Widgets.
>>>>
>>>> Each entry in the Map will be an instance
>>>> of a sub-class of widget; some sub-classes
>>>> may "want" to put more than one entry in the map.

>
> By this, do you mean that a subclass may want to add more than one key,
> each with its own value?
>
>>>> So - how do I populate the map?

>
> Have each class register itself with the parent class's registry as part
> of its static initializer.
>
> public class Sub extends Widget
> {
> static
> {
> synchronized ( Widget.registry )
> {
> registry.put( aKey, someValue );
> registry.put( bKey, otherValue );
> ...
> }
> }
> }
>
> Obviously all get()s from the registry must be synchronized on the
> registry, too.
>
>>>> If I have a static block in each sub-class,
>>>> I have no trivial way of ensuring
>>>> that ALL my subclasses have been referred
>>>> to (thus loading them, and running any static
>>>> code blocks).

>
> Nope. Just the ones that have initialized.
>
> One cannot, in general, determine all subclasses from the parent class,
> because new subclasses can be loaded at any moment, including /just/
> after taking inventory.
>
> OTOH, each subclass knows of its own existence as it's born, thus can
> register itself as part of its initialization. Thus, while you cannot
> determine /a priori/ that each subclass has been registered, each
> subclass can guarantee that it will not be used until it's registered.


Yes. I view this behaviour as more from the "problem ste"
than from the "solution set"

>
>>>> If I have an "init()" method in each sub-class,
>>>> it might be called more than once.

>
> Not if you code it right, make it no more visible than package-private,
> and use a factory method instead of a constructor.


Good Thoughts. Thanks you.


> SadRed wrote:
>>> As the value of the Map, use Collection<Entry> instead of a bare Entry
>>> object.

>
> bugbear wrote:
>> I don't understand what part of my problem this helps;
>> please expand?

>
> It's a bad idea to keep a collection of Map.Entry as a value, if that's
> what was meant by the advice. It might be a good idea to keep a
> Collection<V> or Collection<? extends V> where V is the type of your
> values.
>
> I think SadRed is solving your problem of subclasses registering more
> than one entry, on the reading that you wanted to keep more than one
> value per key, but I'm not sure that's what was meant. I do know that I
> had to read the original post to see if that's what you wanted, or if
> you wanted to keep several values per subclass that have different keys.
>
> One also wonders how you prevent key collisions between subclasses.
> Perhaps you need a key that is a Pair< Class<? extends Widget>, ?
> extends KeyType > as the key to your map. Thus each subclass entry is
> keyed by its own class and its own key values,


Ah - well, this goes to the heart of the modularity/context issue
I'm trying to think about. Clearly (?) the *callers*
of the registry.get() method SOMEHOW know the names
they want to use, so "someone" knows "something".

I guess what this boils down to "who" should know
the names (and existence) of the various widgets,
and how should this knowledge should be aggregated in
(what you nicely called) the registry.

I'm starting to think that the base class is the correct
place for this knowledge, and that a static block
in the base class would be a perfectly "clean" place
to populate the registry by simple performing code along
the lines of:

registry.add("nigel", new WidgetA());
registry.add("george", new WidgetB("arbitrary"));
registry.add("henry", new WidgetB("something"));

BugBear (still coding against 1.4)
 
Reply With Quote
 
Lew
Guest
Posts: n/a
 
      09-03-2007
bugbear wrote:
> I'm starting to think that the base class is the correct
> place for this knowledge, and that a static block
> in the base class would be a perfectly "clean" place
> to populate the registry by simple performing code along
> the lines of:
>
> registry.add("nigel", new WidgetA());
> registry.add("george", new WidgetB("arbitrary"));
> registry.add("henry", new WidgetB("something"));


Indeed. If you take that one step more, you will externalize the sub-class
names to a properties file and let them all have just the default constructor.
Let each subclass handle its own "arbitrary" or "something" in its own
initialization (instance preferred to static). Use Class.newInstance() off
the class object stored as the value, which class object was reflectively
created upon base class static initialization or static init() method (or even
reInit()) based on the externalized properties.

E.g., (untried, uncompiled)

public class Base
{
private static final Map registry = new HashMap();
// or could use Collections.synchronizedMap()

private static void initRegistry()
{
Properties props = getProperties();
Map mappings = new HashMap();
for ( Iterator iter = props.keySet().iterator(); iter.hasNext(); )
{
String key = (String) iter.next();
// here you might have logic to decide whether to use this key
String name = props.getProperty( key );
Class clazz = Class.forName( name ); // try...catch omitted for clarity
mappings.put( key, clazz );
}
synchronized ( registry )
{
registry.putAll( mappings );
}
} // end initRegistry()

private static Properties getProperties()
{
Properties p;
// read the properties from a resource
return p;
}
}

--
Lew
 
Reply With Quote
 
Roedy Green
Guest
Posts: n/a
 
      09-03-2007
On Mon, 03 Sep 2007 10:44:31 +0100, bugbear
<bugbear@trim_papermule.co.uk_trim> wrote, quoted or indirectly quoted
someone who said :

>I would like to have a base class
>"Widget", that amongst other things
>has a method getWidgetFor(String name).
>
>I would like this method to be able to use (e.g.)
>a Widget class static HashMap to look up Widgets.
>
>Each entry in the Map will be an instance
>of a sub-class of widget; some sub-classes
>may "want" to put more than one entry in the map.
>
>So - how do I populate the map?
>
>If I have a static block in each sub-class,
>I have no trivial way of ensuring
>that ALL my subclasses have been referred
>to (thus loading them, and running any static
>code blocks).
>
>If I have an "init()" method in each sub-class,
>it might be called more than once.
>
>I welcome advice, tip, examples, opinions etc.


This is what is called a "factory". Look up the factory design
pattern for some ideas.

Here are three ways you could handle it:

1. create constant array:
PossibleWidgets[] pw = { new Gizmo(), new Thingamabob[]... };

Then loop through the array getting the string name and adding to a
HashMap. Lookup by name. Factory hands out the original or a clone
of the exemplar object.

2. Look in the HashMap for the string to look up an exemplar object (
clone or use original as needed) If it is not there, try
Class.forName, and add it.

3. Turn the string into an enum with valueOf. Let that enum constant
either create the object you want or be the object you want.
--
Roedy Green Canadian Mind Products
The Java Glossary
http://mindprod.com
 
Reply With Quote
 
bugbear
Guest
Posts: n/a
 
      09-04-2007
Lew wrote:
> bugbear wrote:
>> I'm starting to think that the base class is the correct
>> place for this knowledge, and that a static block
>> in the base class would be a perfectly "clean" place
>> to populate the registry by simple performing code along
>> the lines of:
>>
>> registry.add("nigel", new WidgetA());
>> registry.add("george", new WidgetB("arbitrary"));
>> registry.add("henry", new WidgetB("something"));

>
> Indeed. If you take that one step more, you will externalize the
> sub-class names to a properties file and let them all have just the
> default constructor. Let each subclass handle its own "arbitrary" or
> "something" in its own initialization (instance preferred to static).


That's a lot of typing if I want (say) 30 different
objects(instances) in the registry, where some
of them vary in ways that are trivially parameterisable.
e.g. days of week.

(I read your code before snipping)

I guess (as with all code) there's no ONE-size-fits
all solution, which is why programmers still have a job.

BugBear
 
Reply With Quote
 
Lew
Guest
Posts: n/a
 
      09-04-2007
bugbear wrote:
> Lew wrote:
>> bugbear wrote:
>>> I'm starting to think that the base class is the correct
>>> place for this knowledge, and that a static block
>>> in the base class would be a perfectly "clean" place
>>> to populate the registry by simple performing code along
>>> the lines of:
>>>
>>> registry.add("nigel", new WidgetA());
>>> registry.add("george", new WidgetB("arbitrary"));
>>> registry.add("henry", new WidgetB("something"));

>>
>> Indeed. If you take that one step more, you will externalize the
>> sub-class names to a properties file and let them all have just the
>> default constructor. Let each subclass handle its own "arbitrary" or
>> "something" in its own initialization (instance preferred to static).

>
> That's a lot of typing if I want (say) 30 different
> objects(instances) in the registry, where some
> of them vary in ways that are trivially parameterisable.
> e.g. days of week.


It's the same amount of typing whether you load one object or one hundred.
That's the beauty of algorithms - one block of code handles arbitrary data set
sizes.

I don't understand your objection.

--
Lew
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Unable to dispatch an ActionEvent Florence HENRY Java 8 01-10-2005 11:41 AM
java design question: dispatch on subformat? tobin fricke Java 2 06-12-2004 01:51 AM
dispatch in a jsp homecurr@yahoo.com Java 4 04-22-2004 02:29 AM
AWT -> Swing, blocked dispatch thread Miss Elaine Eos Java 2 01-05-2004 02:28 AM
design problem: visitor/multiple dispatch or? Jos A. Horsmeier Java 1 12-02-2003 08:01 PM



Advertisments