我有一系列方法需要顺序运行,将每种方法的结果用作下一个参数。但是,在调用下一个方法之前,我还要检查每个方法的结果是否为“好”(如果“坏”,则我将尽早退出该方法。如果方法不成功,则返回空的Optional
。 / p>
是否可以执行重构以改进代码? 责任链感到有些落伍。
private boolean isSequenceSuccessful() {
Optional<byte[]> result1 = doSomething();
if (!result1.isPresent()) {
return false;
}
Optional<byte[]> result2 = doAnotherThing(result1.get());
if (!result2.isPresent()) {
return false;
}
Optional<byte[]> result3 = doSomethingElse(result2.get());
if (!result3.isPresent()) {
return false;
}
return doMoreStuff(result3.get());
}
我不想使用Exceptions来控制方法的流程,因为那是代码的味道(我希望有时会得到“不好的”结果)。
答案 0 :(得分:3)
您可以使用Optional
和映射将其写得更短:
private boolean isSequenceSuccessful() {
return Optional.of(doSomething())
.flatMap(result1 -> doAnotherThing(result1))
.flatMap(result2 -> doSomethingElse(result2))
.map(result3 -> doMoreStuff(result3))
.orElse(false);
}
或者使用更短的方法引用:
private boolean isSequenceSuccessful2() {
return Optional.of(doSomething())
.flatMap(this::doAnotherThing)
.flatMap(this::doSomethingElse)
.map(this::doMoreStuff)
.orElse(false);
}
这取决于您的喜好。如果要保留中间结果变量,请使用lambda版本。
由于方法doAnotherThing
和doSomethingElse
确实返回了Optional<byte[]>
,因此需要Optional.flatMap
才能继续映射。否则,您可以将这些方法的返回类型更改为仅返回byte[]
。然后,您将只使用Optinal.map
,它将更加一致。
仅当Optional
中存在一个值时,才执行映射。如果可以应用所有映射,则返回最后一个的值作为结果。否则,处理将快速失败,并绕过所有restig映射到最后一个语句orElse
并返回其值。根据您的代码,这是false
。
答案 1 :(得分:0)
您可以使用library(ggplot2)
library(dplyr)
library(reshape2)
library(readr)
data1 <- read_csv("Kaggle.csv")
data2 <- read_csv("country_population.csv")
data2 <- melt(data2, id.vars = c("Country Name", "Country Code", "Indicator Name", "Indicator Code"), variable.name = "Year", value.name = "Population")
data3 <- read_csv("life_expectancy.csv")
data3 <- melt(data3, id.vars = c("Country Name", "Country Code", "Indicator Name", "Indicator Code"), variable.name = "Year", value.name = "Life Expectancy")
years <- unique(data3$Year)
countries <- unique(data3$`Country Name`)
library(shiny)
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
radioButtons(inputId = "secondgraphvariable",
label = "Choose a Variable for the Second Graph",
choices = c("Life Expectancy", "Population"),
selected = "Population"
),
selectInput(
inputId = "years",
label = "Choose years to display",
choices = years,
multiple = TRUE,
selected = c(2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013)
),
selectInput(
inputId = "country",
label = "Choose a country",
choices = countries,
selected = c("Tanzania", "United States", "India", "China"),
multiple = TRUE),
selectInput(
inputId = "xaxis",
label = "Choose a Variable for the X-axis of the First Graph",
choices = colnames(data1),
selected = "Gini coefficient 2005-2013"
),
selectInput(
inputId = "yaxis",
label = "Choose a Variable for the Y-axis of the First Graph",
choices = colnames(data1),
selected = "Gross domestic product GDP percapta"
)
),
mainPanel(
plotOutput(outputId = "scatterplot"))
)
)
server <- function(input, output) {
output$scatterplot <- renderPlot({
req(input$xaxis)
req(input$yaxis)
scatter <- ggplot(data1, aes(x = input$xaxis, y = input$yaxis))+geom_point()
})
}
shinyApp(ui = ui, server = server)
方法:
map
答案 2 :(得分:0)
使用Optional::flatMap
。
private boolean isSequenceSuccessful() {
Optional<Boolean> result = doSomething()
.flatMap(this::doAnotherThing)
.flatMap(this::doSomethingElse)
.map(this::doMoreStuff);
return result.isPresent() ? result.get() : false;
}
答案 3 :(得分:0)
看看模板图案,我有时将其称为披萨图案,因为它类似于制作披萨。 (例如createDough(),putIngredients(),bake(),package(),deliver())。这可能适用于您的情况。这里有几个示例和实现,但是请选择最适合您的示例。在上面的示例中,我将创建一个抽象类并创建具体的类/实现。举例说明:
public abstract class SequenceChecker {
// ...
public boolean isSequenceSuccessful() {
Optional<byte[]> result1 = doSomething();
Optional<byte[]> result2 = doAnotherThing(result1);
Optional<byte[]> result3 = doSomethingElse(result2);
return doMoreStuff(result3);
}
protected abstract boolean doMoreStuff(Optional<byte[]> result);
protected abstract Optional<byte[]> doSomethingElse(Optional<byte[]> result);
protected abstract Optional<byte[]> doAnotherThing(Optional<byte[]> result);
protected abstract Optional<byte[]> doSomething();
// ...
}