Фабрика для иерархии объектов (обходные пути полиморфных статических методов) - PullRequest
3 голосов
/ 25 ноября 2011

Давайте рассмотрим следующую упрощенную иерархию Resource:

public abstract class Resource {
    static public boolean accepts(String resource);
}

public class AudioResource extends Resource {
    static public boolean accepts(String resource) {
        //Check if we can proceed this resource as audio
        //Some complex logic there ...
    }
}

public class VideoResource extends Resource {
    static public boolean accepts(String resource) {
        //Check if we can proceed this resource as video
        //Another complex logic there
    }
}

Resource имеет десятки подклассов и число растет.Каждый подресурс:

  • имеет некоторую логику, чтобы определить, принимает ли он ресурс или нет.Например, он может анализировать URL ресурса с помощью регулярного выражения или чего-то подобного;
  • не является одноэлементным по дизайну;

Теперь мы хотим создать фабрику, которая перебирает все доступные подклассы и создает такую, котораяпринимает ресурс (проверяет его с помощью метода accepts).

Примерно так (предположим на мгновение, что у Java есть полиморфизм статических методов):

public class ResourceFactory {

    private static List<Class<Resource>> registry;
    {
        //Populate registry once on start
    }


    public static Resource createResource(String resource) {
        for (Class<Resource> clazz : registry) {
            if (clazz.accepts(resource)) 
                return clazz.createInstance(resource);
        }
    }    
}  

К сожалению (или нет?), Java не поддерживает полиморфные статические методы. Учитывая это, каковы возможные способы проектирования Resource и ResourceFactory?

1 Ответ

2 голосов
/ 25 ноября 2011

Вы можете использовать:

public interface Resource {
  // some methods
} 

public interface ResourceFactory {
  boolean acceptsResource(String resource);
  Resource createResource(String resource) throws UnsupportedResourceException;
}   

public final MultiResourceFactory implements ResourceFactory{
   private static final ServiceLoader<ResourceFactory > resourceFactoryLoader
       = ServiceLoader.load(ResourceFactory .class);
   private static final MultiResourceFactory INSTANCE;

  private MultiResourceFactory(){
  }

  public static MultiResourceFactory getInstance(){
    if (INSTANCE == null){
        INSTANCE = new MultiResourceFactory();
    }
    return INSTANCE;
  }
  @Override
  public boolean acceptsResource(String resource){
      for (ResourceFactory resourceFactory : resourceFactoryLoader) {
         if (resourceFactory.acceptsResource(resource)){
             return true;
         }
      }
      return false;
  }

  @Override
  public Resource createResource(String resource) throws UnsupportedResourceException{
      for (ResourceFactory resourceFactory : resourceFactoryLoader) {
         if (resourceFactory.acceptsResource(resource)){
             return resourceFactory.createResource(resource);
         }
      }
      throw new UnsupportedResourceException(resource);
  }   

См. ServiceLoader для того, чтобы зарегистрировать фабрики: http://docs.oracle.com/javase/6/docs/api/java/util/ServiceLoader.html

Примечание: код не проверен

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...