【发布时间】:2016-06-15 22:38:07
【问题描述】:
这有合适的名字吗?
public class SomethingFactory {
private final String someParameter;
public SomethingFactory(String someParameter) {
this.someParameter = someParameter;
}
public Something create(String anotherParameter) {
return new Something(someParameter, anotherParameter);
}
}
public class Something {
public final String someParameter;
public final String anotherParameter;
public Something(String someParameter, String anotherParameter) {
this.someParameter = someParameter;
this.anotherParameter = anotherParameter;
}
}
与常规工厂的不同之处在于,您必须在运行时指定一个参数,以便在需要创建对象时进行 create()。
这样你可以在 Spring 上下文中创建一个单例工厂,例如,在那里配置前半部分参数,然后在运行时调用 create() 时完成其余参数。
如果你好奇,我为什么首先需要它:
我曾经在 Spring 上下文中拥有常规的单例对象,并且在每个请求的线程应用程序中都很好,但现在我的整个应用程序是非阻塞的,我不能使用 ThreadLocal 在整个请求处理过程中保留内容。例如,使用 Apache StopWatch 等工具保存时间信息。
我需要找到一种方法来在多线程、非阻塞环境中实现“请求范围”,而不必在我的代码的每个方法(这将是愚蠢的)中提供表示范围的对象。
所以我想让每个(服务)类在构造函数中使用这个范围对象,并在每个请求上创建这些类,但这与单例相违背。我们所说的单例就像是让用户登录的 UserService 或生成数字签名的 CryptoService。它们在 Spring 中配置一次,在需要时注入,一切正常。但现在我需要在需要它们的每个方法中创建这些服务类,而不是仅仅引用注入的单例实例。
所以我认为让我们将这些单例称为“模板”,当您需要一个实际实例时,您可以调用 create() 来提供所述范围对象。这样每个类都有范围对象,您只需将其提供给其他模板服务构造函数。完整的东西看起来像这样:
public class UserService {
private final Scope scope;
private final Template t;
private UserService(Template t, Scope scope) {
this.t = t;
this.scope = scope;
}
public void login(String username) {
scope.timings.probe("before calling database");
t.database.doSomething(username);
scope.timings.probe("after calling database");
}
public static class Template { /* The singleton configured in Spring */
private Database database;
public void setDatabase(Database database) { /* Injected by Spring */
this.database = database;
}
public UserService create(Scope scope) {
return new UserService(this, scope);
}
}
}
public class LoginHttpHandler { /* Also a Spring singleton */
private UserService.Template userServiceT;
public void setUserServiceT(UserService.Template userServiceT) { /* Injected by Spring */
this.userServiceT = userServiceT;
}
public void handle(HttpContext context) { /* Called on every http request */
userServiceT.create(context.scope).login("billgates");
}
}
在 Spring 中,您只需描述一个 UserService.Template bean 及其所需的适当依赖项,然后在需要 UserService 时注入该 bean。
我只是称其为“模板”。但像往常一样,我觉得它已经完成了。有名字吗?
【问题讨论】:
-
建造者模式? javaworld.com/article/2074938/core-java/…(不是 GOF 构建器模式)
标签: java spring design-patterns factory