我是Java的新手,我遇到了以下问题:
我创建了几个实现“Parser”接口的类。我有一个JavaParser,PythonParser,CParser,最后是一个TextParser。
我正在尝试编写一个方法,因此它将采用File或String(表示文件名)并在给定文件扩展名的情况下返回相应的解析器。
这是我基本上试图做的一些伪代码:
public Parser getParser(String filename)
{
String extension = filename.substring(filename.lastIndexOf("."));
switch(extension)
{
case "py": return new PythonParser();
case "java": return new JavaParser();
case "c": return new CParser();
default: return new TextParser();
}
}
一般来说,这是处理这种情况的正确方法吗?另外,我应该如何处理Java不允许切换字符串的事实?我应该使用字符串的.hashcode()值吗?
我觉得有一些设计模式或处理这个问题的东西,但它让我望而却步。这是你怎么做的?
答案 0 :(得分:11)
您可以一个接一个地使用多个if
语句。
您可以为您的语言创建特殊的enum
,并在切换语句中使用它。
您可以使用Map
,其中语言是键,解析器的原型是值。
第三个选项看起来很有趣。代码如下:
return parsers.get(extention).newInstance();
这是使用枚举的第二个选项的一个有点棘手的实现:
enum Language {
JAVA {
public Parser getParser () {
return new JavaParser ();
}},
PYTHON {
public Parser getParser () {
return new PythonParser ();
}},
TEXT {
public Parser getParser () {
return new TextParser ();
}};
public Parser getParser () {
return null;
}
public static Language getLanguage (String extention) {
try {
return valueOf (extention);
} catch (IllegalArgumentException e) {
return TEXT;
}
}
}
...
public Parser getParser(String filename) {
String extension = filename.substring(filename.lastIndexOf("."));
return Language.getLanguage (extension).getParser ();
}
答案 1 :(得分:8)
这称为Factory method pattern,它似乎是处理问题的一种非常好的方法。解决“Java不允许切换字符串”问题的一种方法是使用if
... else
语句。
if (extension.equals("py")) {
return new PythonParser();
}
else if(extension.equals("java")) {
return new JavaParser();
}
else ...
答案 2 :(得分:1)
您可以使用enum
来决定使用哪种语言然后使用它(也在switch语句中):
enum Type { JAVA, PYTHON, CPP, C, PERL };
Type getType(String filename)
{
// do your if chain here
return JAVA;
}
public Parser getParser(String filename)
{
switch(getType(filename))
{
case PYTHON: return new PythonParser();
case JAVA: return new JavaParser();
case C: return new CParser();
default: return new TextParser();
}
}
关于你的第一个问题:你的方法没问题,当你有一些东西可以构建一个接口的多种具体实现时(在你的情况下是Parser
),它被称为工厂模式在运行时选择哪一个
答案 3 :(得分:1)
一般来说,这是正确的方法吗? 处理这种情况?
这似乎是正确的方法,因为PythonParser
,JavaParser
等实现或是Parser
另外,我应该如何处理这个事实 Java不允许打开 字符串?
使用if..else if;您不必使用哈希码或任何东西。查看字符串上的equals()
方法。
我觉得有一些设计 模式或其他东西
答案 4 :(得分:1)
PythonParser,JavaParser和CParser都应该是Parser的子类,或者Parser可以是它们都实现的接口。
您可以使用if / else if。
轻松解决案例陈述的限制请勿使用字符串的哈希码。许多字符串映射到相同的哈希码,因为extension.hashCode()==“java”.hashCode()并不一定意味着extension.equals(“java”)。这里只有3个字符串,意外碰撞的可能性很小,但只要我们幸运,“大部分时间应该工作”的程序都是坏消息。在这种情况下,程序可以完全正确地使用这个特定的字符串集合,然后一段时间后你添加CobolParser并突然它退出工作。
有人提到使用枚举。通常,使用枚举来识别事物的“类型”比使用字符串要好得多。但在这种情况下,您从文件名中提取字符串,因此您必须通过if / else if块运行它以将其转换为枚举,然后测试枚举。当你迅速创建一个特定于类型的解析器时,你不可能保存枚举或再次查看它,所以我认为你没有获得任何东西。
答案 5 :(得分:0)
在这种情况下,使用界面是正确的。您的接口应该公开方法,以便调用类不需要将自己转换为特定的解析器实现。
关于switch case,如果你使用jdk1.5或更高版本,你应该为这些字符串定义enum,你可以轻松使用swicth case。
答案 6 :(得分:0)
我会:
public Parser getParser(String filename) {
String extension = filename.substring(filename.lastIndexOf("."));
if( "py".equals(extension) ) { return new PythonParser() }
if( "java".equals(extension)) { return new JavaParser(); }
if( "c".equals(extension) ) { return new CParser(); }
return new TextParser();
}
关于标题中的问题
如何根据Java中字符串的值返回方法中的不同类型?
你不能只返回一种类型。你可以做的是返回那种类型的子类型,所以如果你的解析器是子类或实现Parser
类/接口,上面的代码将完美地工作。
即。
public interface Parser {
//parser methods
...
}
class PythonParser implements Parser {
// parser implementation
...
}
class JavaParser implements Parser {
// parser implementation
...
}
class CParser implements Parser {
// parser implementation
...
}