Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/336.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为通用工厂构建服务定位器(注册表)_Java_Generics_Factory_Service Locator - Fatal编程技术网

Java 为通用工厂构建服务定位器(注册表)

Java 为通用工厂构建服务定位器(注册表),java,generics,factory,service-locator,Java,Generics,Factory,Service Locator,因此,我有一个服务定位器可以在注册表中查找工厂: public interface Registry { void addFactory(Factory<? extends Component> factory); Factory<? extends Component> getFactory(String name); } 第二个工厂可能看起来像: public class SimpleFactory implements Factory<SimpleC

因此,我有一个服务定位器可以在注册表中查找工厂:

public interface Registry {
  void addFactory(Factory<? extends Component> factory);
  Factory<? extends Component> getFactory(String name);
}
第二个工厂可能看起来像:

public class SimpleFactory implements Factory<SimpleComponent> {
  public SimpleComponent createComponent() {
     return new SimpleComponent();
  }
  public render(SimpleComponent sc) {
    sc.doInThisSC();
  }
}
public class ComplexFactory implements Factory<ComplexComponent> {
  public ComplexComponentcreateComponent() {
     return new ComplexComponent();
  }
  public render(ComplexComponent cc) {
    cc.doInThisCC();
  }
}

我试图表达factory.renderfactory.createComponent应该始终工作,无论发生什么,这样我就可以使用从注册表检索到的任何工厂来实现这一点。

假设您只使用在组件上定义的方法,您可以执行以下操作:

 Registry registry;
 public <X extends Report> void createIt(String name){
     Factory<Component> factory = registry.getFactory(name);
     Component component = factory.createComponent();
     // ...
     factory.render(component);
 }
然后可以将泛型声明为扩展X,并使所有这些方法都对您可用

编辑:

您还可以让Factory成为没有泛型标记的父类,然后让子类型为您处理多态性。然后,每个子类型都可以通过程序的逻辑知道它正在处理它所创建的内容,并自行封装转换以获得更干净的感觉:

public class X implements Component{
    // ...
}

public class XFactory extends Factory{
    @Override
    public Component createComponent(){
        return new X();
    }

    @Override
    public void render(Component in){
        // We know it's an X so we can cast it here:
        X real = (X)in;
        // ...
    }
}

Factoryregistry.getFactoryname;总是会给出一个不加检查的答案warning@Ramanlfc是的,问题是我是否可以更改签名,这样我就不需要强制转换它。这不起作用,factory.render不接受组件它只接受一个C,它已经被定义为扩展组件的东西。这确实很重要,因为只有工厂知道如何处理这种类型的组件。注意,我有一个打字错误,它说报告应该说ComponentComponent根据定义扩展了Component;我想我误解了你在这里的意图。只要您没有使用任何特定的东西来以不同的方式处理不同类型的组件,就可以了。如果你是,并且你不想做铸造,去包装器接口的建议。如果您想以编程方式处理组件类型,这就是强制转换的目的。您还可以为每个要处理的特定子类执行多个签名。您还可以使用特定的工厂子类为您处理多态性,而不是使用泛型语法,这样工厂就可以始终知道它正在返回它生成的类型。这可能还需要在工厂内铸造,但感觉更干净。当你开始变得像这样有点复杂的时候,你有时只需要做演员;Java将它作为一种工具是有原因的。事实上,我可以摆脱泛型,实现一个工厂,使用的实例来获取类型并做出相应的反应,甚至可以为每个类型实现一个工厂。但这里的问题是,我是否可以通过泛型实现这一点,最具体地说,为什么不能。使用泛型方法可以更清楚地知道发生了什么。我认为不可能只使用泛型,因为Java编译器不会公开任何跟踪对象起源的方法。从直觉上看,您所说的是有道理的,但是CFG解析已经够难了,所以我希望每个语句都能独立解析,这意味着它不能建立您在创建对象的同一工厂上调用方法的连接。像Haskell这样更复杂的类型系统可能能够支持这一点,但编写编译器是很困难的,我不确定是否有足够的必要证明实现的合理性。
 Registry registry;
 public <X extends Report> void createIt(String name){
     Factory<Component> factory = registry.getFactory(name);
     Component component = factory.createComponent();
     // ...
     factory.render(component);
 }
public interface X extends Component{
    // Additional methods that will be required in addition to those
    // required by Component
}
public class X implements Component{
    // ...
}

public class XFactory extends Factory{
    @Override
    public Component createComponent(){
        return new X();
    }

    @Override
    public void render(Component in){
        // We know it's an X so we can cast it here:
        X real = (X)in;
        // ...
    }
}