user3369398
user3369398

Reputation: 247

What is the alternative to static in java interface

I have a design question. I have an interface that read XML. Each implementer class read different XML and I want a way to identify which implementer should I dynamically create for the xml type I get. The problem is that java interface can't have static members. What is the best way to do it?

Example:

public interface MyXML{
    public void readXML(String xml);
    public final static String getType();
}

Usage:

func(String xml, String type)
    {
       MyXML obj;

       switch(type)
       {
          case MyImpl.getType():
             obj = new MyImpl();
             break;
         case MyImpl2.getType():
             obj = new MyImpl2();
             break;
      }
      obj.readXML(xml);
   }

EDIT: I'll try to explain better what I want: I need to know which xml can be read by which implementation and I search for a way to force anyone that implements MyXML to tell which xml it can read so I'll not need to maintain the translation outside in another list or factory.

Upvotes: 1

Views: 893

Answers (4)

Marko Topolnik
Marko Topolnik

Reputation: 200148

I suggest you design your system around instances, not types themselves.

The application would instantiate all the XML reader types and would query each instance for the type it is in charge of. You can use that to organize the XML readers into a map and retrieve them with no switch or if-statements.

If there are some heavyweight resources associated with an instance in your current design, then change that design such that all the resource acquisition happens later into the object's lifecycle, not at construction time.

If you need several instances of the same reader at once (for example, in a concurrent setting), then use the idea exemplified by java.util.regex.Pattern and its corresponding Matcher. A pattern is a thread-safe factory of single-threaded, disposable matchers.

Upvotes: 1

Tibor Blenessy
Tibor Blenessy

Reputation: 4420

Java only allow static constants in the interface. In Java 8 you can have also default implementations, but that's a different thing.

One way to solve this is to make getType normal instance method, same as readXML and instantiate implementations in advance, something like this

// somewhere in the constructor or main
List<MyXML> readers = Arrays.asList(new MyImpl1(), new MyImpl2());

public MyXML findReaderForType(String type) {
  for (MyXML reader : readers) {
    if (reader.getType().equals(type)) {
      return reader;
    }
  }
}

However you need to be careful to design your implementations in the way, so they can be reused.

Another option is to create some sort of static factory, which will contain the equivalent of findReaderForType method. Then the mapping between the type and implementation is contained in this factory class.

Upvotes: 2

isah
isah

Reputation: 5341

There's no point in storing implementation types in interface. The interface shouldn't know about implementations. Instead you can store the XML Type in Enum.

enum Type{
TYPE1,
TYPE2;
}

Then you can create a Map<Type, MyXML> variable and add implementations with their corresponding Type in it.

Factory can then be something like:

public MyXml getImplementation(String type){
   Type type = Type.valueOf(type);
   MyXml impl= implementations.get(type);
   if(impl == null){
       throw new UnsupportedOperationException();//or whatever ex you see fit
   }
   return impl;
}

Upvotes: 1

Marcelo Keiti
Marcelo Keiti

Reputation: 1240

Take a look at Factory Design Pattern. The client should call the factory passing the Type, then the factory returns an instance of the correct class:

public class MyFactory {
    public MyXML createMyXML(Type type) {
        return ...
    }
}

This way the client is free from the responsability to know which concrete class needs to be provided.

Upvotes: 1

Related Questions