“绕着执行”这个成语是什么?

我听说过的这个“执行周围”成语(或类似的)是什么?为什么我会使用它,为什么我不想使用它?


答案 1

基本上,这是一种模式,你编写一种方法来做一些总是需要的事情,例如资源分配和清理,并使调用者传递“我们想要对资源做什么”。例如:

public interface InputStreamAction
{
    void useStream(InputStream stream) throws IOException;
}

// Somewhere else    

public void executeWithFile(String filename, InputStreamAction action)
    throws IOException
{
    InputStream stream = new FileInputStream(filename);
    try {
        action.useStream(stream);
    } finally {
        stream.close();
    }
}

// Calling it
executeWithFile("filename.txt", new InputStreamAction()
{
    public void useStream(InputStream stream) throws IOException
    {
        // Code to use the stream goes here
    }
});

// Calling it with Java 8 Lambda Expression:
executeWithFile("filename.txt", s -> System.out.println(s.read()));

// Or with Java 8 Method reference:
executeWithFile("filename.txt", ClassName::methodName);

调用代码不需要担心打开/清理方面 - 它将由.executeWithFile

坦率地说,这在Java中是痛苦的,因为闭包是如此冗长,从Java 8 lambda表达式开始,可以像许多其他语言(例如C#lambda表达式或Groovy)一样实现,并且这种特殊情况自Java 7以来一直使用和流来处理。try-with-resourcesAutoClosable

虽然“分配和清理”是给出的典型例子,但还有很多其他可能的例子 - 事务处理,日志记录,以更多权限执行一些代码等。它基本上有点像模板方法模式,但没有继承。


答案 2

“围绕执行”成语是当你发现自己必须做这样的事情时使用的:

//... chunk of init/preparation code ...
task A
//... chunk of cleanup/finishing code ...

//... chunk of identical init/preparation code ...
task B
//... chunk of identical cleanup/finishing code ...

//... chunk of identical init/preparation code ...
task C
//... chunk of identical cleanup/finishing code ...

//... and so on.

为了避免重复所有这些冗余代码,这些代码总是“围绕”您的实际任务执行,您将创建一个自动处理它的类:

//pseudo-code:
class DoTask()
{
    do(task T)
    {
        // .. chunk of prep code
        // execute task T
        // .. chunk of cleanup code
    }
};

DoTask.do(task A)
DoTask.do(task B)
DoTask.do(task C)

这个成语将所有复杂的冗余代码移动到一个地方,让你的主程序更具可读性(和可维护性!

有关 C# 示例,请查看此文章,查看本文,了解C++示例。