在实例变量中存储函数(Java)
Storing functions in instance variables(Java)
我喜欢存储简单的函数,当它们被其他方法在 class.
中多次使用时,可以将它们表示为私有和最终实例变量中的一行 lambda
此外,有时我会使用未多次使用的函数来执行此操作,以缩短大型方法的长度并更好地表达方法中使用的功能。
public class SomeClass {
private final UnaryOperator<Something> someMethod = s -> doSomething;
public void someMethod2(Something s) {
//some code which goes over several lines and uses someMethod variable
}
public void someMethod3(Something s) {
//some code which goes over several lines and uses someMethod variable
}
}
另一个示例,其中在助手中为不同的服务预先准备了输入 class。必须在两个服务的字符串中替换两个相同的字符。这个函数没有存储在普通的静态方法中,它存储在实现 UnaryOperator 的静态字段中。
public class PrepareServicesInputHelper {
private static final UnaryOperator<String> replaceSignsForAllServices = s -> s.replace('+', '-')
.replace('/', '*');
public static String transformStringForServiceOne(String s) {
return "Additional transformation information for service one" + removeUnwantedSigns.apply(s);
}
public static String transformStringForServiceTwo(String s) {
return "Additional transformation information for service two:" + removeUnwantedSigns.apply(s);
}
}
这样对我来说更好看也更清晰。
这是一个好主意,还是存在一些实际的缺点,或者使用这种方法会损害一些干净代码的范例,并且功能应该以传统方式存储在实例方法中?
在您的示例中,与仅调用方法相比,我看不出您的解决方案有任何附加值。你的解决方案是矫枉过正。
亚伯拉罕·马斯洛 (https://en.wikipedia.org/wiki/Law_of_the_instrument):
I suppose it is tempting, if the only tool you have is a hammer, to treat everything as if it were a nail.
lambda 的正确用例是您需要传递一个函数,或者 select 从多个可能的函数传递给一个函数。在这里,您的用例只是一个简单的 re-use 方法,由 lambda 混淆。
研究行为设计模式here or here,例如命令、Observer/Listener、策略、访问者。在这里你需要 传递 一个行为,这就是在 Java.
中设计的 lambda 的目的
另一个快速"rule of thumb"可能是这样的:
- 您是否需要立即调用方法?所以调用一个方法。
- 你是否需要传递一个方法从另一个方法内部调用,稍后,可能不是调用一次而是多次,甚至可能根本不调用(如果方法在控制决定)?所以传递一个 lambda。
对于您的用例,常用方法是这样的。这样看起来 even 更好并且 even 更清晰:)
public class PrepareServicesInputHelper {
private static String replaceSignsForAllServices(final String s) {
return s.replace('+', '-').replace('/', '*');
}
public static String transformStringForServiceOne(final String s) {
return "Additional transformation information for service one" + removeUnwantedSigns(s);
}
public static String transformStringForServiceTwo(final String s) {
return "Additional transformation information for service two:" + removeUnwantedSigns(s);
}
}
一个很好的例子,与你的相似但不一样,就是这个。您有一个写入文件的记录器,但前提是您打开了日志记录。评估日志文本可能代价高昂,我们只想懒惰地计算它,只在需要时才计算。
public class Logger {
private boolean logIsOn;
// constructor, setters, getters etc.
public log(final String message) {
if (logIsOn) {
printToFile(message);
}
}
public lazyLog(final Supplier<String> message) {
if (logIsOn) {
printToFile(message.get());
}
}
}
// Here the expensive calculation occurs always, even if the logging is off
logger.log("Operation x performed on " +
person.getFirstName() + " " +
person.getLastName() +
" with the result " + result.calculate());
// Here the expensive calculation occurs only when the logging is on
logger.lazyLog(() -> "Operation x performed on " +
person.getFirstName() + " " +
person.getLastName() +
" with the result " + result.calculate());
我喜欢存储简单的函数,当它们被其他方法在 class.
中多次使用时,可以将它们表示为私有和最终实例变量中的一行 lambda此外,有时我会使用未多次使用的函数来执行此操作,以缩短大型方法的长度并更好地表达方法中使用的功能。
public class SomeClass {
private final UnaryOperator<Something> someMethod = s -> doSomething;
public void someMethod2(Something s) {
//some code which goes over several lines and uses someMethod variable
}
public void someMethod3(Something s) {
//some code which goes over several lines and uses someMethod variable
}
}
另一个示例,其中在助手中为不同的服务预先准备了输入 class。必须在两个服务的字符串中替换两个相同的字符。这个函数没有存储在普通的静态方法中,它存储在实现 UnaryOperator 的静态字段中。
public class PrepareServicesInputHelper {
private static final UnaryOperator<String> replaceSignsForAllServices = s -> s.replace('+', '-')
.replace('/', '*');
public static String transformStringForServiceOne(String s) {
return "Additional transformation information for service one" + removeUnwantedSigns.apply(s);
}
public static String transformStringForServiceTwo(String s) {
return "Additional transformation information for service two:" + removeUnwantedSigns.apply(s);
}
}
这样对我来说更好看也更清晰。
这是一个好主意,还是存在一些实际的缺点,或者使用这种方法会损害一些干净代码的范例,并且功能应该以传统方式存储在实例方法中?
在您的示例中,与仅调用方法相比,我看不出您的解决方案有任何附加值。你的解决方案是矫枉过正。
亚伯拉罕·马斯洛 (https://en.wikipedia.org/wiki/Law_of_the_instrument):
I suppose it is tempting, if the only tool you have is a hammer, to treat everything as if it were a nail.
lambda 的正确用例是您需要传递一个函数,或者 select 从多个可能的函数传递给一个函数。在这里,您的用例只是一个简单的 re-use 方法,由 lambda 混淆。
研究行为设计模式here or here,例如命令、Observer/Listener、策略、访问者。在这里你需要 传递 一个行为,这就是在 Java.
中设计的 lambda 的目的另一个快速"rule of thumb"可能是这样的:
- 您是否需要立即调用方法?所以调用一个方法。
- 你是否需要传递一个方法从另一个方法内部调用,稍后,可能不是调用一次而是多次,甚至可能根本不调用(如果方法在控制决定)?所以传递一个 lambda。
对于您的用例,常用方法是这样的。这样看起来 even 更好并且 even 更清晰:)
public class PrepareServicesInputHelper {
private static String replaceSignsForAllServices(final String s) {
return s.replace('+', '-').replace('/', '*');
}
public static String transformStringForServiceOne(final String s) {
return "Additional transformation information for service one" + removeUnwantedSigns(s);
}
public static String transformStringForServiceTwo(final String s) {
return "Additional transformation information for service two:" + removeUnwantedSigns(s);
}
}
一个很好的例子,与你的相似但不一样,就是这个。您有一个写入文件的记录器,但前提是您打开了日志记录。评估日志文本可能代价高昂,我们只想懒惰地计算它,只在需要时才计算。
public class Logger {
private boolean logIsOn;
// constructor, setters, getters etc.
public log(final String message) {
if (logIsOn) {
printToFile(message);
}
}
public lazyLog(final Supplier<String> message) {
if (logIsOn) {
printToFile(message.get());
}
}
}
// Here the expensive calculation occurs always, even if the logging is off
logger.log("Operation x performed on " +
person.getFirstName() + " " +
person.getLastName() +
" with the result " + result.calculate());
// Here the expensive calculation occurs only when the logging is on
logger.lazyLog(() -> "Operation x performed on " +
person.getFirstName() + " " +
person.getLastName() +
" with the result " + result.calculate());