【发布时间】:2014-04-14 09:18:33
【问题描述】:
我正在尝试构建一个工厂对象,但无法找到用 Java 实现它的好方法。
我正在编写的应用程序用于处理各种格式的文件,因此有一个 CodecInterface 适用于所有用于读取和写入文件的类。假设它定义了以下方法。这些文件中的每一个都有一个唯一的人工指定的 ID 字符串,用于标识编码器\解码器。
String read();
void write(String data);
String getID();
工厂类将有一个创建方法,旨在创建这些编解码器类的实例。我想方法签名看起来像这样。
static CodecInterface CodecFactory.create(String filename, String codecid, String args);
filename 是要读取/写入的文件的名称,codecid 是指示要使用的编解码器的唯一 ID。 args 参数是传递给正在生成的解码器/编码器对象的参数字符串。 this 的返回应该是请求的编解码器对象的一个实例。
我见过的所有工厂示例通常在 create 方法中都有一个 switch 语句,它创建一个依赖于 ID 的对象实例。我想避免这样做,因为它看起来不是“正确”的方式,而且这也意味着列表或多或少是固定的,除非您修改 create 方法。理想情况下,我想使用像字典(由编解码器 ID 索引)之类的东西,其中包含可用于创建我想要的编解码器类的实例的东西(我将称之为神秘类 ClassReference)。再次使用一些 quasi-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;
}
}
【问题讨论】:
-
您的
not understanding of what ClassReference should be有何不同,具体取决于您将其作为开关还是字典查找? -
听起来你想看看reflection,尤其是Retrieving Class Objects。
-
Switch 语句意味着我根本不需要担心 ClassReference,因为我可以明确地说如果您请求创建类 FooBar,创建类 Foobar 的实例并返回它。字典意味着我有一个方便的查找,但我需要存储一些东西,然后我可以用它来创建类。
-
关于反射,我一直认为它是一种在运行时检查类\环境结构或动态修改\创建类的方法。不过,我会阅读该链接,因为它似乎与我的搜索所带的位置有些相似。