重构到依赖注入

3

我有一段代码,想将其重构为依赖注入风格。

它目前的样子是这样的:

class MyService {
    public void A(Account account, String someparam1, int someparam2) {
        AccountHandler myHandler = new AccountHandler(account);

        // Do something with AccountHandler...
        myHandler.someMethod1(someparam1);
        myHandler.someMethod2(someparam2);
    }

    // Some more methods with same signature
}

一种方法是注入 AccountHandler 并为每个方法设置账户:
class MyService {

    @Inject
    AccountHandler myHandler;

    public void A(Account account, String someparam1, int someparam2) {
        myHandler.setAccount(account);

        // Do something with myHandler
        myHandler.someMethod1(someparam1);
        myHandler.someMethod2(someparam2);
    }
}

这对我来说很奇怪。 AccountHandler 是(或可以是)一个单例,但它仍然会有一些状态。从理论上讲,在不同的方法中“忘记”调用setAccount而不出现问题是可能的,因为之前的服务方法已经设置了它(除非当然你指定它应该是原型范围的,但仍然...似乎很奇怪)。
class MyService {

    @Inject
    AccountHandler myHandler;

    public void A(Account account, String someparam1, int someparam2) {

        // Do something with myHandler
        myHandler.someMethod1(account, someparam1);
        myHandler.someMethod2(account, someparam2);
    }
}

这只是将问题推给了“AccountHandler”。不管怎样,“AccountHandler”本身会在“someMethod1/2”的开头执行“this.setAccount(account)”,或者它可以让每个方法都没有副作用,这意味着它实际上没有任何状态。这听起来还不错,但我感觉自己可能误解了某些东西。
我认为最符合习惯用法的做法应该是:
class MyService {
    public void A(@Inject AccountHandler myHandler, String someparam1, int someparam2) {
        // Do something with myHandler
        myHandler.someMethod1(someparam1);
        myHandler.someMethod2(someparam2);
    }
}

AccountHandler指的是类似以下的内容:

class AccountHandler {
    @Inject
    Account account;

    public void someMethod1(String someparam1);
    public void someMethod2(int someparam2);
}

在我调用MyService方法之前,我会将Account放在IoC容器的作用域中。我不知道你如何在Java中实际执行此操作。任何指针都将不胜感激。

1个回答

1
您可以注入一个具有createAccountHandler(Account)方法的AccountHandlerFactory,而AccountHandlerFactory将是无状态的单例,而您的AccountHandlers将是有状态但单一对象。

是的,那也是我的最初想法。但是在Google搜索之后,传统智慧似乎认为 工厂模式依赖注入 是解决同一问题的不同方案。我没有看到其他人在 DI 中使用工厂?我看到 Spring 有一个叫做 BeanFactory 的东西,不过不确定它是否适用于这种情况。 - Knut Saua Mathiesen
为什么不呢?我经常看到这样做,通常如果你创建一个工厂,你会创建一个工厂接口,例如你可以使用 AccountHandleFactory 接口以及我提到的方法,然后你可以使用 DI 框架轻松切换 DatabaseBackedAccountHandlerFactory 和 HttpBasedAccountHandlerFactory 实现。此外,它还可以使你的代码更易于测试。BeanFactory 是 Spring 的特定功能,如果你想与 Spring 紧密耦合,可以为 AccountHandler 创建一个原型作用域的 Spring Bean。 - maczikasz
经过一番思考,我同意这确实是最佳解决方案。但我还有一些担忧,如果AccountHandler本身有其他依赖关系,而我又不希望工厂进行处理,那该怎么办呢?不过这是以后要解决的问题。 - Knut Saua Mathiesen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接