一尘不染

Java中没有switch语句的工厂

java

我正在尝试构建工厂对象,但是很难找到一种用Java实现它的好方法。

我正在编写的应用程序用于处理各种格式的文件,因此有一个CodecInterface,适用于用于读写文件的所有类。假设它定义了以下方法。这些文件中的每一个都有一个唯一的人工指定的ID字符串,用于对编码器\解码器进行ID识别。

String read();
void write(String data);
String getID();

工厂类将具有用于创建这些编解码器类实例的create方法。我想方法签名看起来像这样。

static CodecInterface CodecFactory.create(String filename, String codecid, String args);

文件名是要读取/写入的文件的名称,编解码器是指示要使用哪种编解码器的唯一ID。args参数是传递给正在生成的解码器/编码器对象的参数字符串。它的返回应该是所请求的编解码器对象的实例。

我见过的所有Factory示例通常都在create方法内部包含一个switch语句,该语句根据ID创建对象实例。我想避免这样做,因为这似乎不是“正确”的方法,这也意味着除非您修改create方法,否则列表几乎是固定的。理想情况下,我想使用像字典(由编解码器ID索引)之类的东西,其中包含可用于创建所需的编解码器类实例的东西(我将称之为神秘类ClassReference)。再次使用一些准Java代码,这就是我作为create方法的主体所想的。

static Dictionary<String, ClassReference>;

static CodecInterface CodecFactory.create(String filename, String codecid, String args);
{
    ClassReference classreference;

    classreference = codeclibrary(codecid);

    return classreference.instanceOf(args);
}

ID的字典很简单,但是我不知道应该使用什么ClassReference。类引用应该允许我创建所需类的实例,如上例所示。

从网上看,类方法和instanceOf似乎都朝着正确的方向发展,但是我还没有发现任何可以将两者结合在一起的东西。更为复杂的是,要创建的对象的构造函数将带有参数。

我应该看的任何提示将不胜感激。

提前致谢。

感谢大家的建议。最后,我从您的所有建议中总结了一些建议,并提出了以下建议,这些建议似乎很奏效。

请注意,我已经省略了很多“健全性/错误检查”代码以炫耀重要的位。

import java.lang.reflect.Constructor;
import java.util.HashMap;

public class CodecFactory
{
    private static HashMap<String, Class<? extends CodecInterface>> codecs;

    static
    {        
        codecs = new HashMap<String, Class<? extends CodecInterface>>();

        //Register built-in codecs here
        register("codecA", CodecA.class);
        register("codecB", CodecB.class);
        register("codecC", CodecC.class);
    }

    public static void register(String id, Class<? extends CodecInterface> codec)
    {
        Class<? extends CodecInterface> existing;

        existing = codecs.get(id);        
        if(existing == null)
        {
          codecs.put(id, codec);
        }
        else
        {
          //Duplicate ID error handling
        }
    }

    public static CodecInterface create(String codecid, String filename, String mode, String arguments)
    {
        Class<? extends CodecInterface> codecclass;
        CodecInterface codec;
        Constructor constructor;

        codec = null;

        codecclass = codecs.get(codecid);
        if(codecclass != null)
        {
          try
          {
            constructor = codecclass.getDeclaredConstructor(String.class, String.class, String.class, String.class);
            codec = (CodecInterface)(constructor.newInstance(codecid, filename, mode, arguments));
          }
          catch(Exception e)
          {
            //Error handling for constructor/instantiation
          }
        }

        return codec;
    }
}

阅读 337

收藏
2020-12-03

共1个答案

一尘不染

尝试这样的事情:

public class CodecFactory {
    final private static Map<String, Class<? extends CodecInterface>> codecLibrary;

    static {
        codecLibrary = new HashMap<String, Class<? extends CodecInterface>>();
        codecLibrary.put("codec1", Codec1.class);
        //...
    }

    static CodecInterface create(String filename, String codecid, String args) throws InstantiationException, IllegalAccessException {
        Class<? extends CodecInterface> clazz;

        clazz = codecLibrary.get(codecid);

        CodecInterface codec = clazz.newInstance();

        codec.setArgs(args);
        codec.setFilename(filename);

        return codec;
    }
}
2020-12-03