在我们的应用程序中,我看到过这样的代码:
User.java(用户实体)
public class User
{
protected String firstName;
protected String lastName;
...
getters/setters (regular POJO)
}
UserSearchCommand
{
protected List<User> users;
protected int currentPage;
protected int sortColumnIndex;
protected SortOder sortOrder;
// the current user we're editing, if at all
protected User user;
public String getFirstName()
{return(user.getFirstName());}
public String getLastName()
{return(user.getLastName());}
}
现在,根据我的经验,这种模式或反模式对我来说很糟糕。首先,我们将几个问题混合在一起。虽然它们都与用户有关,但它与典型的POJO设计不同。如果我们要走这条路,那么我们不应该这样做吗?
UserSearchCommand
{
protected List<User> users;
protected int currentPage;
protected int sortColumnIndex;
protected SortOder sortOrder;
// the current user we're editing, if at all
protected User user;
public User getUser()
{return(user);}
}
只需返回用户对象,然后我们可以根据需要调用它上面的任何方法?
由于这与典型的bean开发(JSR 303)完全不同,bean验证不适用于此模型,我们必须为每个bean编写验证器。
有没有其他人看到这种设计模式有什么问题,或者我只是作为开发人员挑剔?
沃尔特
答案 0 :(得分:3)
在返回用户对象时,您要让UserSearchCommand在现有数据上写入新信息,这可能不是人们想要允许的,因为搜索应该允许读取数据。此外,您所做的是让使用UserSearchCommand的人必须知道User类中的方法/属性/成员,这在第一个实现中并非如此。
答案 1 :(得分:3)
使用接口的第三个选项怎么样?
UserSearchCommand
{
protected List<User> users;
protected int currentPage;
protected int sortColumnIndex;
protected SortOder sortOrder;
// the current user we're editing, if at all
protected User user;
public I_UserNameDetails getUser()
{
return((I_UserNameDetails)user);
}
}
现在,您可以通过接口进行抽象,并防止修改用户对象。
答案 2 :(得分:2)
Law of Demeter建议第一个例子。
答案 3 :(得分:0)
当Sjoerd和JB生成有效点时,根据你对SearchCommand的使用,我会为第二个例子做出以下参数。如果您在第一个示例中定义的操作不影响UserSearchCommand的行为,那么通过定义getFirstName()等,您实际上只是复制代码,这可能导致可维护性问题,例如,如果稍后您添加一个中间用户类的名称?然后,您不仅需要将其添加到用户,还需要将其添加到UserSearchCommand中的访问者。如果对用户做某事会修改搜索的行为,那么这可能是让调用者通过搜索命令访问用户的有效参数,但这也可以通过PropertyListeners等机制实现。
正如你所指出的那样,第一个例子是将信息混合在一起,对我来说,从OOP的角度来看似乎是违反直觉的。如果要限制对用户访问某些属性,则可能需要更改访问修饰符,或创建公开您认为安全的接口以及公开适当的包/受保护属性的实现类。除非您的UserSearchCommand是用词不当,否则我希望它执行涉及搜索用户的操作,然后将这些用户作为一个单元(而不是用户的单个属性)提供。这是一个搜索命令应该执行与搜索相关的操作,用户应该包含有关用户的信息。
当然这是一个风格问题,但我会投票给你的第二个例子。
答案 4 :(得分:0)
我同意你的看法。我已经看到了同样的技术并且没有看到重点:它只是意味着复制了一大堆代码,为了什么?