[英]Java pattern for parameters of which only one needs to be non-null?
在上一次我经常编写具有多个参数但仅使用其中一个参数的长函数,并且功能仅在散布在函数周围的几个关键点上不同。 因此,拆分函数会在没有目的的情况下创建太多小函数。 这是好风格还是有一个很好的一般重构模式? 更清楚,一个例子:
public performSearch(DataBase dataBase, List<List<String>> segments) {performSearch(dataBase,null,null,segments);}
public performSearch(DataBaseCache dataBaseCache,List<List<String>> segments) {performSearch(null,dataBaseCache,null,segments);}
public performSearch(DataBase dataBase, List<String> keywords {performSearch(dataBase,null,keywords,null);}
public performSearch(DataBaseCache dataBaseCache,List<String> keywords) {performSearch(null,dataBaseCache,keywords,null);}
/** either dataBase or dataBaseCache may be null, dataBaseCache is used if it is non-null, else dataBase is used (slower). */
private void performSearch(DataBase dataBase, DataBaseCache dataBaseCache, List<String> keywords, List<List<String>> segments)
{
SearchObject search = new SearchObject();
search.setFast(true);
...
search.setNumberOfResults(25);
if(dataBaseCache!=null) {search.setSource(dataBaseCache);}
else {search.setSource(dataBase);}
... do some stuff ...
if(segments==null)
{
// create segments from keywords
....
segments = ...
}
}
这种代码风格有效,但是我不喜欢所有这些空参数以及调用这样的方法错误的可能性(两个参数都为null,如果两者都是非空的话会发生什么)但是我不想写4个单独的函数......我知道这可能太笼统但也许有人对这个问题原则有一般解决方案:-)
PS:我不喜欢拆分一个长函数,如果它没有理由除了它很长(即子函数只是按顺序调用,只有这一个函数),特别是如果它们是紧密交织的并且需要在它们周围运输大量参数。
我认为这是非常糟糕的程序风格。 尽量避免这种编码。 由于您已经拥有大量此类代码,因此可能很难对其进行重新分解,因为每个方法都包含自己的逻辑,这与其他方法略有不同。 事实上,很难证明这种风格很糟糕。
我认为你应该使用像这样的行为模式
这可以帮助您将过程代码更改为面向对象。
你能用这样的东西吗?
public static <T> T firstNonNull(T...parameters) {
for (T parameter: parameters) {
if (parameter != null) {
return parameter;
}
}
throw new IllegalArgumentException("At least one argument must be non null");
}
它不会检查多个参数是否不为空且它们必须属于同一类型,但您可以像这样使用它:
search.setSource(firstNonNull(dataBaseCache, database));
期望空值是一种反模式,因为它会使NullPointerExceptions等待发生您的代码。 使用构建器模式构造SearchObject
。 这是你想要的签名,我会让你弄清楚实现:
class SearchBuilder {
SearchObject search = new SearchObject();
List<String> keywords = new ArrayList<String>();
List<List<String>> segments = new ArrayList<List<String>>();
public SearchBuilder(DataBase dataBase) {}
public SearchBuilder(DataBaseCache dataBaseCache) {}
public void addKeyword(String keyword) {}
public void addSegment(String... segment) {}
public void performSearch();
}
我同意亚历克斯的说法。 在不知道问题的情况下,我会根据示例中的内容推荐以下结构:
public interface SearchEngine {
public SearchEngineResult findByKeywords(List<String> keywords);
}
public class JDBCSearchEngine {
private DataSource dataSource;
public JDBCSearchEngine(DataSource dataSource) {
this.dataSource = dataSource;
}
public SearchEngineResult findByKeywords(List<String> keywords) {
// Find from JDBC datasource
// It might be useful to use a DAO instead of datasource, if you have database operations other that searching
}
}
public class CachingSearchEngine {
private SearchEngine searchEngine;
public CachingSearchEngine(SearchEngine searchEngine) {
this.searchEngine = searchEngine;
}
public SearchEngineResult findByKeywords(List<String> keywords) {
// First check from cache
...
// If not found, then fetch from real search engine
SearchEngineResult result = searchEngine.findByKeywords(keywords);
// Then add to cache
// Return the result
return result;
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.