[英]Java code refactoring: multiple instanceof operator usages
考虑下面的示例,其中TextFile
, XmlFile
, HtmlFile
, ShellScriptFile
等类SimpleFile
类的子类。 我正在编写一个FileOperations
类,该类具有一种根据类型搜索通用文件内容的方法。
以下是代码示例:
public searchFile(SimpleFile targetFile, String searchStr) {
if (targetPage instanceof HtmlFile) {
// search html file
}
else if (targetPage instanceof TextFile) {
// search text file
}
else if (targetPage instanceof XmlFile) {
// search xml file
}
else if (targetPage instanceof ShellScriptFile) {
// search shell file
}
...
}
这种结构对我来说很难闻。 我知道这是多态的最佳情况。 但是我无法控制File
类或其子类,因此无法对其进行写入。
还有另一种方法来清理这个烂摊子吗? 因为当我添加对不同文件类型的支持时,if-else结构将不断增加。
否则,如果我坚持使用这种结构,那么Java中最快的运算符的instanceof
是吗? 它对性能有什么影响?
在上述情况下,最好使用getClass()
或isAssignableFrom()
吗?
感谢您的意见或建议!
首先,我想说的是您的例子似乎一点也不差。 这有点冗长,并且可以说不像将它们分成不同的方法那样具有凝聚力,但是对我来说似乎很正常。 我认为更整洁的方法可能是使用重载代替。 我不能说速度的差异,但是从维护和可扩展性的角度来看,将来会更容易处理。
public void searchFile(SimpleFile targetFile , String searchStr) {
// SimpleFile generalized behavior.
if (targetPage instanceof HtmlFile) searchFile((HtmlFile)targetFile, searchStr);
else if (targetPage instanceof TextFile) searchFile((TextFile)targetFile, searchStr);
else if (targetPage instanceof XmlFile) searchFile((XmlFile)targetFile, searchStr);
else if (targetPage instanceof ShellScriptFile) searchFile((ShellScriptFile)targetFile, searchStr);
else System.out.println("Subtype not recognised");
}
public void searchFile(HtmlFile targetFile , String searchStr) {
// HtmlFile specific behavior
}
public void searchFile(TextFile targetFile , String searchStr) {
// TextFile specific behavior
}
public void searchFile(XmlFile targetFile , String searchStr) {
// XmlFile specific behavior
}
public void searchFile(ShellScriptFile targetFile , String searchStr) {
// ShellScript specific behavior
}
如果有一个新的SimpleFile
子类,它将默认为该方法的SimpleFile
版本。 如果在编译时不知道类型(如注释中所述),则可以使用最通用的searchFile()
方法来相应地检查和重新分配对象。
编辑:作为对多次使用instanceof
的性能影响的注释, 共识似乎是无关紧要的,并且无论如何,现代instanceof的使用非常快 。
如果可以修改File
及其子类,则可以尝试使用Visitor模式。 既然不能,我建议您将类型测试switch语句合并为一个方法,以便只需要修改一个开关。
public Enum FileHandler {
HTML(){
public search(File file, String searchstr){ /* ... */}
public prettyPrint(File file){ /* ... */}
},
XML(){ /* ... */};
// ... end list of enum implementations
public static FileHander get(File file){
// Put your master switch statement here
if (targetPage instanceof HtmlFile) {
return HTML;
}
else if (targetPage instanceof XmlFile) {
return XML;
}
// ...
}
}
您使用enum类的代码将看起来像这样,避免了可怕的switch语句:
public searchFile(SimpleFile targetFile, String searchStr) {
FileHandler.get(targetFile).search(targetFile, searchStr);
}
您可以使用解释器设计模式或责任链设计模式来解决此问题。 这些模式似乎只是解决此问题的完美方法。
解释器设计模式的示例,如果您需要责任链设计模式的示例,请评论
客户:
public Integer wordCountOnPage (Page samplePage)
{
ArrayList list = new ArrayList<Page>();
list.add(new XmlPage());
list.add(new HtmlPage());
list.add(new JsonPage());
for (int index = 0 ; index < list.size(); index ++)
{
Page eachPage = (Page) list.get(index);
if (eachPage.intercept(samplePage)){
Integer i = eachPage.wordCountOnPage(samplePage);
}
}
return 1;
}
public class XmlPage implements Page {
@Override
public Boolean intercept(Page page) {
// TODO Auto-generated method stub
return page instanceof XmlPage;
}
@Override
public Integer wordCountOnPage(Page page) {
// TODO Auto-generated method stub
return null;
}
}
public interface Page {
Boolean intercept(Page page);
Integer wordCountOnPage(Page page);
}
我的方法是使用执行业务逻辑的单个方法创建接口FileSearcher
。 为每种文件类型创建此接口的一个实现。 然后,创建一个注册表,该注册表将SimpleFile
子类SimpleFile
到其对应的FileSearcher
实现。 在搜索文件方法中,而不是执行instanceof
检查, FileSeacher
在运行时查找匹配的FileSeacher
实现并将其委托给它。
有了这个实现你可能会遇到麻烦时,有子类HtmlFile
等,因为你必须映射HtmlFileSearcher
到的所有子类HtmlFile
。 在这种情况下,将另一个方法添加到FileSearcher
,名为canHandle(Class<SimpleFile> runtimeClass)
,该方法允许FileSearcher
实现来表示它们理解什么文件类。 在注册表中,而不是在地图中查找,而是遍历所有已注册的FileSearchers
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.