简体   繁体   English

重构许多类似方法的代码

[英]Refactoring the code of many similar methods

Hi I have many similar methods in my code as below and maybe I will have more in the future. 嗨,我的代码中有很多类似的方法,如下所示,也许将来还会有更多类似的方法。

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);
}

Above methods are some kind of filters which returns data based on eg type of the book, issue date of the book. 上面的方法是某种过滤器,其基于例如书的类型,书的发行日期返回数据。

And the question is, if it is possible to refactor the code of all that kind of methods? 问题是,是否可以重构所有这种方法的代码? Or maybe better to follow above scheme? 还是更好地遵循上述方案? Thanks for the answers 感谢您的回答

You can create a method called getBooksWithPredicate : 您可以创建一个名为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);
}

This is basically a generalization of all three of the methods shown. 这基本上是所显示的所有三种方法的概括。 The three methods can then be implemented by calling this method: 然后可以通过调用此方法来实现这三种方法:

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);
}

There are multiple solutions to your problem. 您的问题有多种解决方案。

For the getParticularBook() method, you can have a separate HashMap<String,Book> , so that you need not iterate through all the books every time. 对于getParticularBook()方法,您可以有一个单独的HashMap<String,Book> ,因此您不必每次都遍历所有书籍。 This will work only if there are no duplicates. 仅在没有重复项的情况下才有效。

For the getBooksDataOnRange() method, you can have a HashMap<Integer, ArrayList<Book>> where the integer will be the year and the ArrayList will contain the list of books published in that year. 对于getBooksDataOnRange()方法,您可以具有HashMap<Integer, ArrayList<Book>> ,其中整数将是年份,而ArrayList将包含该年出版的书籍列表。 If memory is an issue here, you can have a HashMap<Integer, ArrayList<String>> where instead of storing the book object, you will be storing the name of the book. 如果这里有内存问题,则可以使用HashMap<Integer, ArrayList<String>> ,在该目录中将存储书籍的名称,而不是存储书籍对象。 You can get the book object from the previous HashMap. 您可以从以前的HashMap获取book对象。

For the getBooksDataOnType() method, I guess the actual requirement is to get the data of all the books of the given type. 对于getBooksDataOnType()方法,我想实际的要求是获取给定类型的所有书籍的数据。 Here I would suggest a HashMap<String, ArrayList<String>> if a single book can have multiple types. 如果一本书可以具有多种类型HashMap<String, ArrayList<String>>在这里我建议使用HashMap<String, ArrayList<String>> If not, and if memory is not an issue for you, then you can have a HashMap<String, ArrayList<Book>> for this. 如果不是这样,并且如果内存不是您的问题,则可以为此使用HashMap<String, ArrayList<Book>>

Here are the Java Documentation links to HashMap and ArrayList. 这是指向HashMap和ArrayList的Java文档链接。 This would help you with the implementation. 这将对您的实施有所帮助。

HashMap: https://docs.oracle.com/javase/8/docs/api/java/util/HashMap.html 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 ArrayList: https : //docs.oracle.com/javase/8/docs/api/java/util/ArrayList.html

There are many different options to do it. 有很多不同的选择可以做到这一点。 And the basic idea is to separate the iteration on the books from the testing if a book matches your search. 基本思想是,如果一本书与您的搜索匹配,则将书中的迭代与测试分开。

For example some kind of command pattern and passing a method that compares two books: 例如某种命令模式并传递比较两本书的方法:

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

Then you can pass different comparators to that method - for example title comparator, years comparator etc. 然后,您可以将不同的比较器传递给该方法-例如标题比较器,年份比较器等。

Another (and a better) way to do it is if you look at how Hibernate queries data. 另一种(也是一种更好的)方法是查看Hibernate如何查询数据。 Create something like "BookSearchCriteria" class. 创建类似“ BookSearchCriteria”类的内容。 Something like: 就像是:

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

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

And your method will become: 您的方法将变为:

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

This would be a better example because you can extend that criteria in many ways - for example combining properties, making it AND or OR criteria etc. 这将是一个更好的示例,因为您可以通过多种方式扩展该条件-例如组合属性,使其成为AND或OR条件等。

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

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