我有一个现有的方法,如下所示:
public void parseMessage(String message){
...
...
...
}
并通过调用方法调用该方法,如下所示
String message;
parseMessage(message);
我需要对其进行修改才能处理新类型的消息。从parseMessage方法调用的新类型消息的解析器在解析消息之前首先需要一些属性。我正在考虑做的是将消息作为一个看起来像这个
的对象传递public class MessageObject{
private String message;
private String namespace;
private String xmlVersion;
}
然后我可以将现有方法称为
Object messageObject;
parseMessage(messageObject);
然后我可以通过将其作为(MessageObject)messageObject进行转换来使用它。
这是正确的做法还是有更好的方法。做上述事情有危险吗?
PS。我必须使用上面的转换方法作为im使用JDK1.4
由于
我无法修改parseMessage方法。它内部有一个调用,它为每个相关的解析器调用parse()方法。
public void parseMessage(String message){
...
...
parser.parse(message)
}
上面显示的解析器引用是一个实现接口“Parser”的对象。我正在介绍的新解析器遵循这种结构,它还实现了“Parser”接口。唯一的修改(即对MessageObject的转换)在新的解析器中。
我无法更改现有的parseMethod,因为这将需要更改实现“Parser”界面的所有现有解析器。我想避免根据消息类型调用特定的解析器。
如果我使用我建议的方法,现有的解析器仍将收到String消息,而新的解析器将收到一个String,但它需要先将它强制转换回MessageObject。
我必须根据谢尔盖的评论对此进行测试。
界面
package com;
public interface Parser{
public void parse(String message);
}
package com;
MessageA Parser
public class MessageAParser implements Parser{
public void parse(String message){
System.out.println("Parsing A");
}
}
MessageB Parser
package com;
public class MessageAParser implements Parser{
public void parse(String message){
System.out.println("Parsing A");
}
}
MessageC解析器(这需要一个对象)
package com;
public class MessageCParser implements Parser{
public void parse(Object message){
MessageObject mobject = (MessageObject)message;
System.out.println("Parsing C" + mobject.getMessage());
}
public void parse(String m){}
}
调用相关解析器的解析器管理器。
package com;
import java.util.HashMap;
public class ParserManager{
public ParserManager() {
prepare();
}
HashMap parsers = new HashMap();
public void prepare(){
parsers.put("A",new MessageAParser());
parsers.put("B",new MessageBParser());
parsers.put("C",new MessageCParser());
}
public void parseMessage(String msgType, String message){
((Parser)parsers.get(msgType)).parse(message);
}
}
package com;
控制器。
public class ControlClass{
public static void main(String[] args){
ParserManager pManager = new ParserManager();
//Parse A
pManager.parseMessage("A","ATEXT TO PARSE");
//Parse B
pManager.parseMessage("B","BTEXT TO PARSE");
//Parse C
Object mobject = new MessageObject();
pManager.parseMessage("C",(String)mobject);
}
}
当我运行上面的Controller类时,它输出前两个消息的文本但是第三个消息失败。
Parsing A
Parsing B
java.lang.ClassCastException
at com.ControlClass.main(ControlClass.java:17)
Exception in thread "main"
答案 0 :(得分:2)
您可以重载parseMessage,因此它有两种形式:一种采用String参数,另一种采用MessageObject参数。
答案 1 :(得分:2)
MessageObject类不是String子类,因此您无法传递它而不是String。而且你不能将String子类化,因为它被声明为final。所以你无法将MessageObject(无论是什么)传递给现有的parseMessage()函数。
我无法更改现有的parseMethod 因为这将需要改变所有 实现的现有解析器 “Parser”界面。我想要 避免必须调用特定的解析器 取决于消息类型。
Parser.parse()的签名究竟是什么?如果它是parse(String message)
,那么除了字符串之外你不可能传递任何东西。
但是,如果这是您不想修改现有parseMessage()的唯一原因,那么有一种解决方法:
public void parseMessage(Object message) { // changed to Object
...
...
if (message instanceof String)
parser.parse((String) message);
else {
if (message instanceof MessageObject) {
if (!(parser instanceof MessageObjectParser)) {
throw new IllegalArgumentException(
"A MessageObject is passed, but not supported by the parser");
}
((MessageObjectParser) parser).parse((MessageObject) message);
} else {
throw new IllegalArgumentException(
"Messages of type " + parser.getClass() + " aren't supported");
}
}
}
这有点难看,但可能会奏效。现在,您只有新的解析器实现了新的MessageObjectParser接口,该接口应该扩展旧的Parser。
答案 2 :(得分:1)
我认为这里有一些更清洁的解决方案。第一个是你可以扩展实现parseMessage的类并添加一个额外的方法。
public void parseMessage(MessageObject messageObject) {
// Additional stuff here
...
// Call through to original
parseMessage(messageObject.message);
}
或者,您可以装饰包含parseMessage的类。但是,我假设你可以修改包含parseMessage的类,因为你说你想把它放在那里。
答案 3 :(得分:1)
如果你要解析越来越多的东西,而不是重载parse方法,你应该引入一个接口:
public interface Parseable {
public String getMessage();
}
MessageObject将实现Parseable,您可以为String对象使用匿名适配器类:
final String m = "theMessageToParse";
parseMessage(new Parseable() {
public String getMessage() {
return m;
}
});