繁体   English   中英

Java代码重构:操作员用法的多个实例

[英]Java code refactoring: multiple instanceof operator usages

考虑下面的示例,其中TextFileXmlFileHtmlFileShellScriptFile等类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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM