简体   繁体   中英

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.

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.

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.

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;
}

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM