设计服务启动界面

时间:2011-01-20 22:15:08

标签: java class-design

简单的答案当然是在Service接口上包含一个start方法。

interface Service {
   void start();
   OperationResult operation( parameters );
   ...
}

这当然是sux,因为服务的大多数用户不想要或不关心启动服务,他们只想使用像操作这样的方法。

你会如何解决这个问题?我有一个简单的解决方案,它确实有一个主要的限制,而不会污染服务接口,因此我想听听人们的建议。

4 个答案:

答案 0 :(得分:1)

如果有必要启动服务,然后用它做事,然后可能终止服务,应该有一个对象,其功能只是启动服务并提供一个对象,然后可以用来做东西该服务,包括终止它(后一个动作 - 可能最好通过IDisposable处理 - 应该使“do-stuff”对象无效)。

答案 1 :(得分:0)

有几种方法:

  • 每当构建时启动它
  • 如果服务未启动,则从操作方法中抛出异常,指示使用不当
  • 自动从每个方法启动它,如果它没有启动

答案 2 :(得分:0)

您的问题出现了,因为您正在混合实现问题(start()方法,例如)和actions(operation()方法)。 Start是一个实现问题,因为您可以为每个调用者创建一个实例,或者您可以拥有一个单例(如在缓存实例中)。调用者根本不应该调用该方法。实际上,如果您明天保留start方法并将实现更改为单例,则代码可能会停止为现有客户端工作。

IMO,你应该从这个界面摆脱start方法,让调用者担心委派你的操作方法最好的任务。

如果将启动方法(与界面无关的优化步骤)推送到实现,则可以通过多种方式解决问题。例如,

一个。如果在operation()方法之前没有调用它,则调用start()。您将需要处理同步问题。 湾在实现对象的构造函数中调用start()并完成它。

答案 3 :(得分:0)

如果您不希望消费者关心调用启动。您可以考虑将您的启动代码内部委托给一个受保护的方法,该方法在启动时初始化您当前正在执行的操作。如:

    protected MyService getMyService() {
    if(myService == null) {
        myService = new MyServiceImpl();
        myService.startup();
    }
    return idpPersistence;
}

调用这样的方法:

public String findByThis(String tag, String key) {
    return getMyService().findThat(MyClass.class, column, key);
}

这当然有一些权衡。如果您在启动时服务费用很高,那么第一个来电者首先会接受该命中。

另一种选择是使用静态{}块来实现这些,但当然有时候也不是很容易测试。此外,在对象构造上执行启动例程,这有时也会违反IOC模式。我去添加了一个Service接口,因为我拥有的客户端是内部的,我希望所有服务都在初始化时准备就绪。