将函数存储在实例变量中(Java)

时间:2019-06-20 12:57:57

标签: java-8 functional-programming object-oriented-analysis method-reference functional-interface

我喜欢存储简单的函数,当类中的其他方法多次使用它们时,这些函数可以在私有和最终实例变量中表示为一行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
    }
}

另一个示例,该示例在帮助程序类中为不同的服务预先输入。对于两个服务,必须在字符串中替换两个相同的字符。此函数未存储在普通的静态方法中,而是存储在实现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);
    }
}

看起来更好,这对我来说更清晰

这是一个好主意吗?是否存在一些实际的缺点或使用这种方法损害了一些干净代码范例的功能,功能应该以传统方式存储在实例方法中?

1 个答案:

答案 0 :(得分:1)

在您的示例中,与简单地调用一个方法相比,我看不到您的解决方案的任何附加价值。您的解决方案太过分了。

亚伯拉罕·马斯洛(https://en.wikipedia.org/wiki/Law_of_the_instrument):

  

如果您仅有的工具是锤子,我想把所有东西都当作钉子来对待是很诱人的。

lambda的正确用例是您需要传递一个函数,或从多个可能的函数中选择一个函数。在这里,您的用例只是对方法的简单重用,而这种方法被lambda所混淆。

研究行为设计模式herehere,例如命令,观察者/侦听器,策略,访问者。在这里,您需要传递行为,而这正是lambda在Java中设计的目的。

另一个快速的“经验法则”可能是这样:

  1. 您是否需要立即调用方法 ?因此调用方法。
  2. 您是否需要传递一个方法,以便稍后从另一个方法内部调用,可能一次调用一次,但是多次调用,甚至根本没有调用(如果控制方法决定这样做)?因此,传递一个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());