views:

148

answers:

7

In Java, I'd like to be able to define marker interfaces, that forced implementations to provide static methods. For example, for simple text-serialization/deserialization I'd like to be able to define an interface that looked something like this:

public interface TextTransformable<T>{

  public static T fromText(String text);

  public String toText();

Since interfaces in Java can't contain static methods though (as noted in a number of other posts/threads: here, here, and here this code doesn't work.

What I'm looking for however is some reasonable paradigm to express the same intent, namely symmetric methods, one of which is static, and enforced by the compiler. Right now the best we can come up with is some kind of static factory object or generic factory, neither of which is really satisfactory.

Note: in our case our primary use-case is we have many, many "value-object" types - enums, or other objects that have a limited number of values, typically carry no state beyond their value, and which we parse/de-parse thousands of time a second, so actually do care about reusing instances (like Float, Integer, etc.) and its impact on memory consumption/g.c.

Any thoughts?

EDIT1: To clear up some confusion - we have many, different objects fitting this pattern -really we're trying to come up with something elegant for callers with 2 semantics:

  • Interfaces as contracts - unity of access (e.g. TextTransformable as a capability)
  • Requiring implementation by subclasses/implementations (e.g. force them to implement their own transformation

In terms of our thoughts for Flyweight, Factories - they're both options we've considered, really we're trying to see if we can find something more elegant though than relying on JavaDoc saying "implement a Factory and delegate calls to it, or expose it at XXX location by convention"

+1  A: 

If you are running in Java 5 or higher, you can use the enum type - all of those are, by definition, singletons. So you could something like:

public enum MyEnumType {
    Type1,
    Type2,
    //....
    TypeN;

    //you can do whatever you want down here
    //including implementing interfaces that the enum conforms to.

}

This way the memory problem goes away, and you can have single instances of behavior implemented.


Edit: If you don't have access to enums (1.4 or earlier) or, for some other reason, they don't work for you, I would recommend a Flyweight pattern implementation.

aperkins
You can see below for why we're trying to come up with a convention to go beyond the capabilities built into the enum support in Java 5+
jayshao
@jayshao We had a similar problem with the valueof, and worked around it. But I think a flyweight pattern, with a singleton registry of sorts, would work around a large part of that issue for you, as further explained by @Yishai
aperkins
@aperkins any sample code?
jayshao
@jayshao I can see if I have any at home when I get there later this evening.
aperkins
@jayshao: I see @Yishai has edited his answer, and I think that his flyweight example is pretty good - I would take a look at it.
aperkins
@perkins - yes, after tossing around internally some variation of the flyweight is probably where we're going to end up, but again, parts of it just don't feel right - though we're of course constrained by the expressiveness of the language
jayshao
@jayshao: this does seem to be a common problem with any language. Some things are just not possible to correctly express given the abstraction. Good luck with it.
aperkins
A: 

You could also use singleton design pattern:

public interface SingletonFactoryFunctor {
   /**
    * @return An instance of the Singleton.
    */
   public Singleton makeInstance();
}
MUG4N
See above - our core concern is *not* resource usage, but semantics of callers (we have many of these objects) and I don't think singleton is really appropriate for this case.
jayshao
+2  A: 

Just an idea to consider: You can separate the transformation logic from the objects themselves, and then you have a fixed set of transformers, implementing the following interface :

public interface Transformer<T>{ 

  public T fromText(String text); 

  public String toText(T obj); 
}

Your actual data classes can have a method getTransformer() that returns the right transformer for them.

Eyal Schneider
mother bleeper! you beat me to it! :)
LES2
we're hoping to keep code co-located - these are basically just value objects so ideally this is a big part of what they do
jayshao
A: 

As @aperkins said, you should use enums.

The enum base class, Enum, provides a valueOf method that will convert a string to an instance.

enum MyEnum { A, B, C; }
// Here's your toText
String strVal = MyEnum.A.getName();
// and here's your fromText
MyEnum value = MyEnum.valueOf(MyEnum.class, strVal);

Update: For the ones that are enums, this might do what you need. It uses reflection, so you only need to implement EnumHelper on enums where you have to deal with legacy values.

/** Enums can implement this to provide a method for resolving a string
  * to a proper enum name.
  */
public interface EnumHelp
{
    // Resolve s to a proper enum name that can be processed by Enum.valueOf
    String resolve(String s);
}

/** EnumParser provides methods for resolving symbolic names to enum instances.
  * If the enum in question implements EnumHelp, then the resolve method is
  * called to resolve the token to a proper enum name before calling valueOf.
  */
public class EnumParser
{
    public static <T extends Enum<T>> T fromText(Class<T> cl, String s) {
        if (EnumHelp.class.isAssignableFrom(cl)) {
            try {
                Method resolve = cl.getMethod("resolve", String.class);
                s = (String) resolve.invoke(null, s);
            }
            catch (NoSuchMethodException ex) {}
            catch (SecurityException ex) {}
            catch(IllegalAccessException ex) {}
            catch(IllegalArgumentException ex) {}
            catch(InvocationTargetException ex) {}
        }
        return T.valueOf(cl, s);
    }

    public <T extends Enum<T>> String toText(T value)
    {
        return value.name();
    }
}
Devon_C_Miller
Many of the existing objects are Enums already, though unfortunately since Enum doesn't allow overriding valueOf() our ability to produce good textrepresentations (default values, null-safe, support past versions, encodings, etc.) is limited - hence our desire to implement separate methods - but with similar semantics, just more power in our ability to customize.
jayshao
Nothing stops you from adding a custom lookup method to your enum if you don't like the behavior of valueOf(). You'll often do that if you need a lookup method that returns null or a default value if nothing can be found. With valueOf() you can only do that with try / catch which puts exception handling in charge of control flow
seanizer
A: 

It seems like you need to separate the factory out from the created object.

public interface TextTransformer<T> {
    public T fromText(String text);
    public String toText(T source);
}

You can register TextTransformer classes however you like:

public class FooTextTransformer implements TextTransformer<Foo> {
    public Foo fromText(String text) { return ...; }
    public String toText(Foo source) { return ...; }
}

If you want FooTextTransformer to be a singleton, you can use a container like Spring to enforce that. Google has initiated a project to remove all manually enforced singletons from their codebase, but if you want to do an old-fashioned singleton, you could use a utility class:

public class TextTransformers {
    public static final FooTextTransformer FOO = new FooTextTransformer();
    ...
    public static final BarTextTransformer BAR = new BarTextTransformer();
}

In your client code:

Foo foo = TextTransformers.FOO.fromText(...);
...
foo.setSomething(...);
...
String text = TextTransformers.FOO.toText(foo);

This is just one approach off the top of my head.

LES2
+1  A: 

This is really appropriate for the Flyweight. That is basically what you are trying to accomplish with the statics. In terms of how to serve the Flyweight object so that you don't create thousands of them, here are some ideas.

One is the factory, which you state you thought about and rejected, although you didn't state why (so any other ideas may suffer from the same problem) so I won't go into it.

Another is to have the value type have a method which can serve its converter. Something like this:

 public class ValueType {
       public static final TextTransformable<ValueType> CONVERT = ....
 }

And then use it like this:

 ValueType value = ValueType.CONVERT.fromText(text);

 String text = ValueType.CONVERT.toText(value);

Now that doesn't enforce that all ValueType's provide their converters via the same mechanism, for that I think you need a factory of some kind.

Edit: I guess I don't know what you find inelegant about a factory, but I think you are focused on callers, so how does this feel to you:

  ValueType value = getTransformer(ValueType.class).fromText(text);

The above can be done with a static import of the factory and a method that has a signature like so:

   public static <T> TextTransformable<T> getTransformer(Class<T> type) {
         ...
   }

The code to find the right transformer isn't necessarily the prettiest, but from the callers perspective everything is nicely presented.

Edit 2: Thinking about this further, what I see is that you want to control object construction. You can't really do that. In other words, in Java you can't force an implementer to use or not use a factory to create their object. They can always expose a public constructor. I think your problem is that you aren't happy with the mechanisms for enforcing construction. If that understanding is right, then the following pattern may be of use.

You create an object with only private constructors which wraps your value type. The object may have a generic type parameter to know what value type it wraps. This object is instantiated with a static factory method which takes a factory interface to create the "real" value object. All framework code that uses the object only takes this object as a parameter. It does not accept the value type directly, and that object cannot be instantiated without a factory for the value type.

The problem with this approach is that it is quite restricting. There is only one way to create objects (those supported by the factory interface) and there is limited ability to use the value objects, as the code processing these text elements has limited interaction only through this object.

I guess they say there isn't a software problem that can't be solved via an extra layer of indirection, but this may be a bridge too far. At least its food for thought.

Yishai
Yes, I'll edit above with the note that we've talked about flyweight - really though I think we're focused on the unity of access (e.g. like a marker interface, and enforcing contract on subclass) - neither of which a factory or static transformer feel like they get us)The main reason I think we're not happy with the factory idea is it feels inelegant, though admittedly sometimes we put up with inelegance when we can't come up with something elegant...
jayshao
Yes, ironically restricting is what we want ;) Ideally more of a mix-in, but without having to use a collaborator object - though I agree, your summary is similar to our current thinking and likely as good as we're going to be able to come up with for now.
jayshao
A: 

A totally different approach (and an ugly hack, for that matter) is to let the interface have a method that returns a method.

public interface MyInterface{
    Method getConvertMethod();
}

now your client code can do

yourInterface.getConvertMethod().invoke(objectToBeConverted);

This is extremely powerful, but very bad API design

Sean

seanizer
that's interesting actually - in JS I'd do it in a heartbeat, or some other language where Functors were common, in Java it feels a bit odd though
jayshao
exactly, as methods are not "first class citizens" in Java. This may however change soon in JDK1.7. We'll see how much that changes programming style...
seanizer