虽然我从未见过它被严格记录在案,但我通常使用“服务”一词来表示处理某些相关最终用户功能子集的类。
例如,假设我有一个银行账户系统,我可能有以下服务:
public class AccountService
{
public boolean transfer(Account src, Account dest, double amt) // ....
public Account create(User user, double initAmt) // ...
public void close(Account account) // ...
}
所以用户可以做的“高级”功能都封装在我的服务中。服务将访问数据库,实例化任何助手,进行计算等它需要的。但就像我说的,这正是我在这个行业中观察到的。
就 SRP 而言:SRP 并不意味着您需要为每个要执行的功能创建一个全新的类。您不需要一个类将配置文件标记为失败,另一个将其标记为成功,另一个来更改配置文件的名称......
SRP 意味着每个类处理“一件事”,但“一件事”可以是一组密切相关的功能。另一个需要考虑的重要 OO 设计原则是封装。也就是说,一个类应该尽量减少它暴露给客户的东西——只暴露其他人需要的东西。如果您有大量的小类来管理 PaymentProfile 的内部状态,那么您将暴露 PaymentProfile 的所有细节。我给你举个小例子:
假设您的 PaymentProfile 对象有一个布尔值 isSuccess。然后你的类 RecurringPaymentProfileMarkAsFailedService 做这样的事情:
public class RecurringPaymentProfileMarkAsFailedService {
public void mark(PaymentProfile profile)
{
profile.setSuccess(false);
}
}
酷 - 一切正常。现在我们收到一个功能请求,不仅 PaymentProfile 可以具有“成功”和“失败”状态,而且现在我们需要支持“内部错误”,这意味着某些内部系统在更新期间崩溃了。我们不能再使用布尔值,因此我们将布尔值 isSuccess 更改为可以是以下之一的枚举:SUCCESS、FAILURE、ERROR。现在我们必须重构我们的 MarkAsFailedService。
这是一个微不足道的重构 b/c 它只是一个类,但是对于一个复杂的类树,这些重构可以在整个系统中回显。这表明我透露了太多关于我的 PaymentProfile 的实现细节。一个类应该被封装,因此对其实现的更改对其客户端几乎没有影响。