“开始”,“运行”或“执行”方法是一种好习惯吗?


30

我目前正在开发具有许多实现Start方法的类的代码库。在我看来,这似乎是两阶段构建,我一直认为这是一种不良做法。我不能说这和构造函数之间的区别。

什么时候适合使用start方法而不是普通的对象构造方法?

我何时应该更喜欢使用构造函数?

编辑:我不认为这是相关的,但是编程语言是C#,它同样适用于Java或C ++


3
您可以添加更多上下文吗?语言?线程还是单线程?start和构造函数之间的区别?等等...

@MichaelT我明白您为什么要问我,但是我对适当时要遵循的一般原则感兴趣。我担心如果我从正在使用的代码库中给出具体示例,答案将过于侧重细节而不是我的特定问题。
Dave Hillier

2
@DaveHillier例如,在perl中init,在new函数-perldoc.perl.org/perlobj.html之外拥有某种方法是一种标准做法(也是一种很好的做法)。一种语言的习语可能在那里很好地工作,而不是其他语言。

1
Start通用API中带有方法的类的示例包括线程和秒表。
luiscubal

1
在需要代码示例以了解您实际要求的人员中,请数我。
user16764 2013年

Answers:


44

当构造对象的成本很低但使用它的成本很高时,一种Start()方法(如或类似的东西)是合适的。例如:封装最佳路径优化算法的类。使用一组参数(使用诸如此类的评估方法逐个平方)来设置它是很简单的,但是可能要花一些时间才能执行。如果要创建这些对象中的20个,则可能需要延迟执行,直到创建了所有对象为止-例如,这使您可以更轻松地并行化它们。Run()Execute()XY

另外,当您不知道何时需要启动该对象时,它可能会很有用-可能是因为它基于用户输入或从可能性列表中选择的逻辑。

当然,这假定Start()是对象上的有用方法,而不是等效于Initialize()方法。如果这只是设置更多参数的一种额外方法,那么它就不应该存在。


1
启动方法的另一个用途是,完成的操作还会创建新的工作线程或计时器。构造函数不应执行此类繁重的工作,也不应产生明显的副作用(例如创建新线程)。
2013年

50

代码完成(以及许多其他软件工程资源)强调将您的类与实际对象匹配。我相信,这样做的根本原因是,它使您更有可能真正掌握要实施的内容,而不是费力地放弃一个无形的想法。

如果您是该理论的订阅者,那么将Start()方法添加到任何类(如果它是真实对象)也应该具有静止状态,我认为不会有任何问题。如果在不运行时对对象的存在没有任何意义(或者说对对象的运行完全没有意义),那么我会说这是一种不好的做法。


16
一个很好的类比。值得注意的是,它Start()可能对应于开/关开关(例如电灯开关),然后应该有一个Stop(),或者对应一个按钮(例如复印机上的“打印”按钮),在该按钮上它会启动然后运行直到完成。
Bobson

3
+1说得好,欢迎来到P.SE,像这样的答案是一个不错的开始。
Jimmy Hoffa 2013年

14

您可以使用延迟初始化。

在计算机编程中,延迟初始化是将对象的创建,值的计算或其他昂贵的过程延迟到第一次需要时才进行的策略。

这样就避免了时间耦合,这意味着您的类的使用者必须按特定的顺序调用特定的方法。必须start()先调用是一种必须知道类在内部如何工作的方式,这很不好,因为您将来可能会更改它。

将昂贵的初始化延迟到第一次需要。

例:

public class FooClass{

    private ExpensiveResource resource;
    private CheapResource cheap;

    public  FooClass(String someParameter){
        // constructor: initialize CheapResource cheap 
            // but NOT ExpensiveResource resource
    }

    public ExpensiveResource getExpensiveResource(){
        if (resource == null) {
            this.initializeExpensiveResource();     
        }
        return this.resource
    }

    public String getExpensiveResourceName(){
        if (resource == null) {
            this.initializeExpensiveResource();     
        }
        return this.resource.getName();
    }   

    public CheapResource getCheapResource(){
        return this.cheap;
    }

    private initializeExpensiveResource(){
        // do expensive initialization of field "resource"
    }

}

public class Test{
    public static void main (String args[]){

        FooClass foo = new FooClass("some string");
        CheapResource cr = foo.getCheapResource();
        String s = foo.getExpensiveResourceName(); 
          // just now is the expensive resource initialized

    }
}

5
值得注意的是,延迟初始化的另一个好处是,只需很少的精力即可将其形成为虚拟代理。根据情况的不同,这对于在等待资源加载时显示某些内容可能非常有用(尤其对于远程映像之类的实用程序)。基于最初的问题,我不认为这实际上是OP所要求的,但值得一提。
丹·艾伯特

@DanAlbert,您说得对,这不是我想要的,但仍然很有趣
Dave Hillier
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.