让我们考虑以下示例:
class User
{
}
class FirstUseNotification
{
function show(User user)
{
// check if it was already shown, return if so
// show a notification
// mark it as shown in the db or whatever
}
}
class SomeController
{
function someMethod()
{
firstUseNotification->show(user);
}
}
show()方法似乎通过做三件事打破了单一职责。所以我认为可以这样重写:
class User
{
}
class FirstUseNotification
{
function show(User user)
{
// show a notification
}
function shouldShow(User user)
{
// return true if not yet shown
}
function markAsShown(User user)
{
// flag notification as shown
}
}
class SomeController
{
function someMethod()
{
if (firstUseNotification->shouldShow(user))
{
firstUseNotification->show(user);
firstUseNotification->markAsShown(user);
}
}
}
所以这就是我感兴趣的内容:
一个班级只有一个改变的理由。
在这种情况下,您的FirstUseNotification
类的目的是向新用户显示通知。因此,该类需要更改的唯一原因是该目的是否更改;这是原因之一,因此可以满足SRP。
请注意,此定义适用于类,而不适用于方法。就是说,将此方法分为三个方法可能会[违反] SRP,因为如果此类的用户需要调用三个方法而不是一个,则该用户类负责检查是否显示通知,并且如图所示标记用户,
除了用户类的责任。 FirstUseNotification
的责任是“向首次使用的用户显示通知”,而不是提供一个API,该API允许其他类在不承担责任的情况下执行此操作。实际上,如果FirstUserNotification
类的详细信息如何显示通知或访问数据库,则可能会有其他更改的原因。理想情况下,可以通过为通知和数据库类具有稳定的接口来防止这种情况,以使对那些类的更改不需要更改FirstUseNotification
或其他显示通知和/或访问数据库的类。实际上,这并非总是100%实现的,在这种情况下,FirstUseNotification
类可能与显示通知或访问数据库的细节有关。但是从理论上讲,如果那些其他阶级适当地处理自己的职责,那么这一阶级只有一个改变的理由。