Inner Interface - no!

V

VisionSet

I have a class that is instantiable via a few factory methods.
Each method produces a slightly different object that uses or doesn't
various attributes.
To make the public interface better I want the factory methods to return
different interface types.

I thought I'd have different inner interfaces that describe the contracts of
the objects returned by the factory methods.

But my class must implement these and I get 'cyclic inheritance
involving...' errors.

How do you typically implement this pattern, has it got a name?
 
J

John C. Bollinger

VisionSet said:
I have a class that is instantiable via a few factory methods.
Each method produces a slightly different object that uses or doesn't
various attributes.
To make the public interface better I want the factory methods to return
different interface types.

I thought I'd have different inner interfaces that describe the contracts of
the objects returned by the factory methods.

But my class must implement these and I get 'cyclic inheritance
involving...' errors.

How do you typically implement this pattern, has it got a name?

Evidently, either the interfaces must not be nested in the class in
question or the objects you return must be of a subclass of your class.
In the latter case, the subclass can be trivial; for instance, this
compiles fine for me:

public class C {

public static interface I {
void foo();
}

public void foo() {}

public static I getInstance() {
class CI extends C implements I {}

return new CI();
}
}

I wouldn't say that that's something I typically do, though.

As for as the name of the pattern? As I understand it, you want to have
a class that clients use to obtain objects suitable (and perhaps
suitably configured) for various specific uses. That would be the
Factory pattern; probably a static factory in this case for the fewest
changes from what you already have. Once you hide the fact that the
objects returned by your factory are instances of the factory class (by
assigning them to the appropriate interface type) then that detail is no
longer relevant. Clients of the class cannot assume it to be the case
unless you document it, and if you're going to document it then why are
you bothering with the exercise in the first place?

I'm guessing that that wasn't what you were hoping to hear regarding the
pattern name, but I'm not sure how else to answer the question. Perhaps
it's because I don't understand why you want to do quite what you first
described (that gives the compiler error). If you want to hand out
objects of different declared types then why is it important that they
all be instances of the same class? Or to turn it the other way around,
if it is important that the objects you want to hand out all be
instances of the same class then what do you gain by declaring them with
some narrower type?


John Bollinger
(e-mail address removed)
 
V

VisionSet

John C. Bollinger said:
Evidently, either the interfaces must not be nested in the class in
question or the objects you return must be of a subclass of your class.
In the latter case, the subclass can be trivial; for instance, this
compiles fine for me:

public class C {

public static interface I {
void foo();
}

public void foo() {}

public static I getInstance() {
class CI extends C implements I {}

return new CI();
}
}

I wouldn't say that that's something I typically do, though.

As for as the name of the pattern? As I understand it, you want to have
a class that clients use to obtain objects suitable (and perhaps
suitably configured) for various specific uses. That would be the
Factory pattern; probably a static factory in this case for the fewest
changes from what you already have. Once you hide the fact that the
objects returned by your factory are instances of the factory class (by
assigning them to the appropriate interface type) then that detail is no
longer relevant. Clients of the class cannot assume it to be the case
unless you document it, and if you're going to document it then why are
you bothering with the exercise in the first place?

I'm guessing that that wasn't what you were hoping to hear regarding the
pattern name, but I'm not sure how else to answer the question. Perhaps
it's because I don't understand why you want to do quite what you first
described (that gives the compiler error). If you want to hand out
objects of different declared types then why is it important that they
all be instances of the same class? Or to turn it the other way around,
if it is important that the objects you want to hand out all be
instances of the same class then what do you gain by declaring them with
some narrower type?

Your analysis of my situation is quite correct.
I'm not pursuing that approach any longer.
Let me elaborate

I need to create 1 of 3 different simple GUIs.
they all have some elements in common with each other

UI1 has widgetA, widgetB
UI2 has widgetB
UI3 has widgetA, widgetA, widgetC

So I can't use simple inheritence.

And I don't want to duplicate code.

I was looking at the builder pattern, but can't quite see that it fits here.

Originally I had all the widgets in one class and was using Factory methods
to build the relevent component, but as you point out - 'why is it important
that they all be instances of the same class?'

My latest thought is that I have a static factory class for producing the
widgets and the return type is an interface that allows me to get & set the
text on each one.

Thanks John!
 
J

John C. Bollinger

VisionSet said:
I need to create 1 of 3 different simple GUIs.
they all have some elements in common with each other

UI1 has widgetA, widgetB
UI2 has widgetB
UI3 has widgetA, widgetA, widgetC

So I can't use simple inheritence.

And I don't want to duplicate code.

I was looking at the builder pattern, but can't quite see that it fits here.

Originally I had all the widgets in one class and was using Factory methods
to build the relevent component, but as you point out - 'why is it important
that they all be instances of the same class?'

My latest thought is that I have a static factory class for producing the
widgets and the return type is an interface that allows me to get & set the
text on each one.

So in this way you protect your ability to change the implementation
class(es) of the widgets in the future if you need to do? That's a
reasonable aim, and a reasonable method of achieving it. May I suggest
that you include a method such as

public Component asComponent();

in your interface(s) so as to avoid having to cast the objects in order
to place them in the GUI? Or does that defeat the purpose?

You may find it useful to implement two levels of factories: the one we
have already discussed that creates widgets, and one that, using the
first factory, creates whole GUIs. Note also that everything becomes
more flexible as you go from static factory to non-static factory to
abstract factory; you should consider which flavor is the most
appropriate for the perceived future needs of the software. (If you do
use two factories then you may choose different points along that
spectrum for them.)

I have been known to design with non-static, concrete factories that are
nevertheless written in such a way as to enable a painless shift to
abstract factories later. The way to do so is to make the factory's
constructor inaccessible, and require clients to obtain an instance via
a static method on the factory class (i.e. MyFactory getInstance();).

I hope some of this helps.


John Bollinger
(e-mail address removed)
 
V

VisionSet

John C. Bollinger said:
So in this way you protect your ability to change the implementation
class(es) of the widgets in the future if you need to do? That's a
reasonable aim, and a reasonable method of achieving it. May I suggest
that you include a method such as

public Component asComponent();

in your interface(s) so as to avoid having to cast the objects in order
to place them in the GUI? Or does that defeat the purpose?

That makes sense, I'm sure I'd have done that.
You may find it useful to implement two levels of factories: the one we
have already discussed that creates widgets, and one that, using the
first factory, creates whole GUIs. Note also that everything becomes
more flexible as you go from static factory to non-static factory to
abstract factory; you should consider which flavor is the most
appropriate for the perceived future needs of the software. (If you do
use two factories then you may choose different points along that
spectrum for them.)

I have been known to design with non-static, concrete factories that are
nevertheless written in such a way as to enable a painless shift to
abstract factories later. The way to do so is to make the factory's
constructor inaccessible, and require clients to obtain an instance via
a static method on the factory class (i.e. MyFactory getInstance();).

I hope some of this helps.

Yes, the confirmation is nice!

I'm familiar with static factories & abstract factories, not sure I've come
across non-static factories. Is there an example in the 1.4 API?

Thanks John.
 
J

John C. Bollinger

VisionSet said:
I'm familiar with static factories & abstract factories, not sure I've come
across non-static factories. Is there an example in the 1.4 API?

The main difference between a concrete, non-static factory and an
abstract factory is that with the former you don't have to provide a
means to specify what concrete class will be used for the factory --
it's hardcoded into the factory class as that class itself. Both
provide their factory services in the form of instance methods, which
means that you can override them with a subclass if you wish, and that
you can you can achieve thread safety more easily if your factory needs
to maintain state (you can have multiple instances with independent
state). In some cases there may be other advantages to independent
state as well.

I did a search for "Factory" in the API docs, and came up with several
hits. One that seems to follow this pattern is
javax.swing.text.DefaultFormatterFactory, although I'm not sure that's
the best available example. Note that although DefaultFormatterFactory
is a subclass of
javax.swing.JFormattedTextField.AbstractFormatterFactory, its abstract
superclass is not an abstract factory in the sense that I normally use
the term because it doesn't provide any means to get a hold of an
instance. (E.g. a static method for that purpose.)


John Bollinger
(e-mail address removed)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,431
Messages
2,571,677
Members
48,796
Latest member
Greg L.

Latest Threads

Top