Fluent接口风格

这个故事我早就想说了,可能是在好多个月前,只是一直不知道怎么说才能说合适,现在我重新整理了一下,讲述给大家。

 

这个故事是从下面这样一个对外暴露接口的调用开始的。

QueryUserEvent event = new QueryUserEvent();
event.setName(name);
event.setAge(18);
event.setType(QueryUserEvent.TYPE_NORMAL);
event.setSex(QueryUserEvent.SEX_MALE);
……
List<User> userList = userService.query(event);

 我想做的事情其实很简单,我想查询一个用户列表,可是接口参数的拼装让我感到头疼,这样的代码太过啰嗦,我希望有可读性更好的解决办法。

P兄台说,如果我直接传入一个user对象

User user = new User();
user.setName(name);
user.setAge(18);
user.setSex(QueryUserEvent.SEX_MALE);
……
List<User> userList = userService.query(user, UserService.QUERY_TYPE_NORMAL);

 

我有时候会考虑你说的办法的,可是,你没有解决实际的问题,我现在的最大问题在于,这一堆的setXXX方法,它破坏了我构造这个查询条件对象的流畅性。

 

他紧接着说,那要不然,我们把setXXX方法的劳动省下来,让构造器来替我们完成这个任务吧:

,是不是可以避开了这个未必带来多少好处的event?

User user = new User(name, 18, QueryUserEvent.SEX_MALE, ……);
List<User> userList = userService.query(user, UserService.QUERY_TYPE_NORMAL);

 

我说,你的办法看起来不错,不过有时候按你的办法做,我的构造方法会变得臃肿无比,比如出现十多个参数;

另外还有一个问题,假如说,我的查询条件是简单的(我只需要根据年龄查询),那么其它的参数都要写成null,类似这样子

 

User user = new User(null, 18, null, null, null, null, ……);
List<User> userList = userService.query(user, UserService.QUERY_TYPE_NORMAL);

 

天,让谁去阅读这样的代码,他都不会喜欢的。

而且,有时候情形变得复杂,比如,我不是要查询18岁的所有user,而是要查询大于18岁的所有user,你的办法似乎行不通了呢……

 

你真是一个麻烦的人,他说,这样吧,我定义一个Condition,他给查询条件带来了灵活的组装方式:

UserQueryCondition condition = new UserQueryCondition();
condition.setAge(Condition.GREATER_THAN, 18);
List<User> userList = userService.query(condition, UserService.QUERY_TYPE_NORMAL);

 不过,他补充道,如果在JavaScript中,我可以采取的办法要好得多。如果要查询18岁的和符合其他条件的用户,可以这样写:

userService.query({
    name : name,
    age : 18,
    sex : User.SEX_MALE
}, UserService.QUERY_TYPE_NORMAL);

如果要大于18岁呢,可以这样写:
userService.query({
    name : name,
    greaterThan : {
        age : 18
    },
    sex : User.SEX_MALE
}, UserService.QUERY_TYPE_NORMAL);

 

不过,他接着说,在Java里面好像还没有类似简洁的表示方法……

 

万幸的是,有一种接口连续调用的风格,叫做“Fluent Interface”,可以让这个问题写成这样一种有趣的实现:

 

List<User> userList = new UserService().setName(name).setAge(18).setSex(User.SEX_MALE).query(UserService.QUERY_TYPE_NORMAL);

 大于18岁的话,这样写:

List<User> userList = new UserService().setName(name).greaterThan(new User().setAge(18)).setSex(User.SEX_MALE).query(UserService.QUERY_TYPE_NORMAL);

 对于Fluent Interface而言,它的接口调用既改变了对象的状态,又返回了对象(this或其他),并不属于上面的两种类型。


转自
https://blog.csdn.net/RayChase/article/details/84149666
posted @ 2020-10-03 22:27  *乐途*  阅读(160)  评论(0)    收藏  举报