繁体   English   中英

重构许多类似方法的代码

[英]Refactoring the code of many similar methods

嗨,我的代码中有很多类似的方法,如下所示,也许将来还会有更多类似的方法。

public void getParticularBook(String nameOfBook){
    String bookDetails = "";
    Iterator<Book> iterator = allBooks.iterator();
    while(iterator.hasNext()) {
        Book b = iterator.next();
        if(b.getTitle().equalsIgnoreCase(nameOfBook)){
            bookDetails = b.toString();
        }
    }
    System.out.println(bookDetails);
}

public void getBooksDataOnRange(int from, int to){
    String bookDetails = "";
    Iterator<Book> iterator = allBooks.iterator();
    while(iterator.hasNext()) {
        Book b = iterator.next();
        if(b.getIssueYear() >= from && b.getIssueYear() <= to){
            bookDetails = b.toString();
        }
    }

    if(bookDetails.isEmpty()){
        System.out.println("No books in range of: " + from + "-" + to);
    }
    System.out.println(bookDetails);
}

public void getBooksDataOnType(String type){
    String bookDetails = "";
    Iterator<Book> iterator = allBooks.iterator();
    while(iterator.hasNext()) {
        Book b = iterator.next();
        if(b.getType().equalsIgnoreCase(type)){
            bookDetails = b.toString();
        }
    }

    if(bookDetails.isEmpty()){
        System.out.println("No books of type: " + type);
    }
    System.out.println(bookDetails);
}

上面的方法是某种过滤器,其基于例如书的类型,书的发行日期返回数据。

问题是,是否可以重构所有这种方法的代码? 还是更好地遵循上述方案? 感谢您的回答

您可以创建一个名为getBooksWithPredicate的方法:

public static void getBooksWithPredicate(Predicate<Book> predicate, String errorMessage) {
    String bookDetails = "";
    Iterator<Book> iterator = allBooks.iterator();
    while(iterator.hasNext()) {
        Book b = iterator.next();
        if(predicate.test(b)){
            bookDetails = b.toString();
        }
    }

    if(bookDetails.isEmpty()){
        System.out.println(errorMessage);
    }
    System.out.println(bookDetails);
}

这基本上是所显示的所有三种方法的概括。 然后可以通过调用此方法来实现这三种方法:

public void getParticularBook(String nameOfBook){
    getBooksWithPredicate(b -> b.getTitle().equalsIgnoreCase(nameOfBook), "");
}

public void getBooksDataOnRange(int from, int to){
    getBooksWithPredicate(b -> b.getIssueYear() >= from && b.getIssueYear() <= to, "No books in range of: " + from + "-" + to);
}

public void getBooksDataOnType(String type){
    getBooksWithPredicate(b -> b.getType().equalsIgnoreCase(type), "No books of type: " + type);
}

您的问题有多种解决方案。

对于getParticularBook()方法,您可以有一个单独的HashMap<String,Book> ,因此您不必每次都遍历所有书籍。 仅在没有重复项的情况下才有效。

对于getBooksDataOnRange()方法,您可以具有HashMap<Integer, ArrayList<Book>> ,其中整数将是年份,而ArrayList将包含该年出版的书籍列表。 如果这里有内存问题,则可以使用HashMap<Integer, ArrayList<String>> ,在该目录中将存储书籍的名称,而不是存储书籍对象。 您可以从以前的HashMap获取book对象。

对于getBooksDataOnType()方法,我想实际的要求是获取给定类型的所有书籍的数据。 如果一本书可以具有多种类型HashMap<String, ArrayList<String>>在这里我建议使用HashMap<String, ArrayList<String>> 如果不是这样,并且如果内存不是您的问题,则可以为此使用HashMap<String, ArrayList<Book>>

这是指向HashMap和ArrayList的Java文档链接。 这将对您的实施有所帮助。

HashMap: https//docs.oracle.com/javase/8/docs/api/java/util/HashMap.html

ArrayList: https : //docs.oracle.com/javase/8/docs/api/java/util/ArrayList.html

有很多不同的选择可以做到这一点。 基本思想是,如果一本书与您的搜索匹配,则将书中的迭代与测试分开。

例如某种命令模式并传递比较两本书的方法:

public void getBooks(Book testAgainst, Comparator<Book> comparator){
iterate
comparator.compare(bookFromIterator, testAgainst);
print result if matches  
}

然后,您可以将不同的比较器传递给该方法-例如标题比较器,年份比较器等。

另一种(也是一种更好的)方法是查看Hibernate如何查询数据。 创建类似“ BookSearchCriteria”类的内容。 就像是:

class BookSearchCriteria {
  int fromYear;
  int toYear;
  String title;

  public boolean matches(Book book){
        ... test for title, test for year etc...
   }
}

您的方法将变为:

public void getBooks(BookSearchCriteria  criteria){
iterator
....
if(criteria.matches(book)) then do stuff
}

这将是一个更好的示例,因为您可以通过多种方式扩展该条件-例如组合属性,使其成为AND或OR条件等。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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