Java 基于前提条件创建新实例的最佳方法

Java 基于前提条件创建新实例的最佳方法,java,Java,嗨,我的问题是这个。假设您有一个定义如何实现转换器的接口。此接口可以有一个loadDocument()方法和另一个convert()。现在假设我们想要有多个转换器,ConvertHTML2DOC,ConvertXML2HTML e.t.c,你就知道了 假设您在两个字符串中获得了需要转换的两种格式(不管您如何获得它们)。现在您需要创建转换器的实例并转换文档 我的问题是哪一个更好:实际创建一个详细的if语句,还是通过类的反射加载类?为了证明我写了一个小例子来说明我的意思。在我的示例中,有两个类P1和

嗨,我的问题是这个。假设您有一个定义如何实现转换器的接口。此接口可以有一个loadDocument()方法和另一个convert()。现在假设我们想要有多个转换器,ConvertHTML2DOC,ConvertXML2HTML e.t.c,你就知道了

假设您在两个字符串中获得了需要转换的两种格式(不管您如何获得它们)。现在您需要创建转换器的实例并转换文档

我的问题是哪一个更好:实际创建一个详细的if语句,还是通过类的反射加载类?为了证明我写了一个小例子来说明我的意思。在我的示例中,有两个类P1和P2共享一个接口。我还创建了50000个,以显示速度差异。事实证明,正常调用的速度稍快一些,但我认为在一个复杂的示例中,如我在开头提到的示例中,通过Class方法创建类的好处更方便,也更易于维护。你的想法是什么

import java.util.*;

public class Test {
  public static void main(String[] args) {
    try {
      Random r = new Random();
      Date test1start = new Date();
      for (int i = 0; i<= 50000; i++){
        Printable p = (Printable)Class.forName("P"+(r.nextInt(2)+1)).newInstance();
        System.out.println(p.getString());
      }
      Date test1stop = new Date();
      Date test2start = new Date();
      for (int i = 0; i<= 50000; i++){
        Printable p;
        if (r.nextInt(2) == 0 ) {
           p = new P1();
        } else {
          p = new P2();
        }
        System.out.println(p.getString());
      }
      Date test2stop = new Date();
      System.out.println("Test with 'Class' invocation took "+(test1stop.getTime()-test1start.getTime())+" milliseconds.");
      System.out.println("Test with 'normal' invocation took "+(test2stop.getTime()-test2start.getTime())+" milliseconds.");
    } catch (Exception e) {
    }
  }
}

interface Printable {
  public String getString();
}

class P1 implements Printable {
  public String getString(){
    return "1";
  }
}

class P2 implements Printable {
  public String getString(){
    return "2";
}
  }
import java.util.*;
公开课考试{
公共静态void main(字符串[]args){
试一试{
随机r=新随机();
日期test1start=新日期();

对于(inti=0;i请尝试这样的方法,编译时安全性,使用一行Class.forName

public class PrintableFactory
{
    public enum Type
    {
        HTML,
        DOC,
    }

    public static Printable getPrintable(final Type from, final Type to)
    {
        final Printable printable;

        if(from == HTML && to == DOC)
        {
            printable = new HtmlToDoc();
        }
        else if(from == DOC && to == HTML)
        {
            printable = new DocToHTML();
        }
        else
        {   
            // you decide if you want runtime or compile time exception handling
            // could also return numm but I don't like that myself.
            throw new ImpossibleConversionException(from, to);
        }

        return (printable);
    }
}

当然要使用工厂方法;但是不要使用“big
if
”或名称混乱,而是使用“class registration”方法。为此,工厂类维护一个表,每个具体类在其中注册它的条件(在您的例子中是源和目标名)和构造函数(它是一个“条件->构造函数”字典).工厂本身只是构造字典键并获取它所需的构造函数


一个最大的优点是,每个具体类都封装了它所解决的条件,并且您可以在不更改工厂方法的情况下添加更多的条件。

您肯定应该遵循Javier的建议-工厂注册是解决此问题的正确方法。我在过去多次以这种方式实现它,用于格式转换或者其他一些可扩展的基于“谓词”的工厂解决方案(例如,基于反射信息的GUI自动生成)

然而,我建议在设计中增加一项内容,即引入一个通用域模型(CDM),该模型是所有翻译人员的目标。假设您有格式a、B和C,您需要支持每种格式之间的转换,您可以获得所有排列:

  • A->B
  • A->C
  • B->A
  • B->C
  • C->A
  • C->B
随着格式数量的增加,您会得到大量的转换!更好的方法是将每个转换分为两部分——我们称之为导入器和导出器。导入器将格式转换为公共域模型(CDM),而导出器将格式从CDM转换为某种格式

例如,我们将从A到B的转换分解为以下内容:

  • A-->CDM(这是一个导入)
  • CDM-->B(这是一个导出)
现在,当你想添加一个新的格式时,你只需要编写一个导入器和导出器,但你可以从所有其他格式中得到翻译!谈论可扩展的!它还允许你可以读取但不能写入的格式,反之亦然


因此,解决方案是建立进口商工厂和出口商工厂的注册。

好吧……你不喜欢这样做是因为?如果你不说你为什么反对投票,你怎么能期望人们从反对投票中学到一些东西?可能是因为它缺乏OP显然试图实现的可扩展性?