使用额外参数扩展所有方法而不声明它们

时间:2014-03-14 08:59:53

标签: java

我有以下界面:

public interface HszService {

    Response<User> getUsers();

    Response<Item> getItems();

    Response<Item> getItems(ItemType type);

}

每个方法都可以在API中使用int pageint pagesize参数调用。

是否可以使用这些参数间接扩展上述方法?我真的想避免像以下那样定义它:

public interface HszService {

    Response<User> getUsers();

    Response<User> getUsers(int page, int pagesize);

    Response<Item> getItems();

    Response<Item> getItems(int page, int pagesize);

    Response<Item> getItems(ItemType type);

    Response<Item> getItems(ItemType type, int page, int pagesize);

}

处理它的最佳模式是什么?

4 个答案:

答案 0 :(得分:1)

有很多方法可以解决这个问题:

  1. 为两个int值PageProperties创建一个可选的包装器, 如果使用null,则在服务实现中,恢复为 默认值。界面如下所示:

    public interface HszService {
        Response getUsers(PageProperties optionalPageProperties);
        Response getItems(PageProperties optionalPageProperties);
        Response getItems(ItemType type, PageProperties optionalPageProperties);
    }
  2. (至少我不喜欢说...)为服务添加状态:

    public interface HszService {
        void setPageProperties(int page, int pageSize);
        Response getUsers();
        Response getItems();
        Response getItems(ItemType type);
    }
  3. 您可以强制用户输入值,并为默认值提供getter:

    public interface HszService {
        int getDefaultPage();
        int getDefaultPageSize();
        Response getUsers(int page, int pageSize);
        Response getItems(int page, int pageSize);
        Response getItems(ItemType type, int page, int pageSize);
    }
  4. 还有很多其他方法。你可以在这里使用各种模式,因为这是一个非常简单和常见的情况。我不想在这里讨论所有的设计模式,因为它超出了这个答案的范围,但你可以在网上找到很多关于它们的信息。

答案 1 :(得分:0)

我认为间接传递参数不是一个好习惯,因为API是间接的。我认为您应该使用所需的参数扩展API。

但无论如何......你可以使用ThreadLocal

public interface HszService {

    public static final ThreadLocal<PagingParams> PAGING_PARAMS = new  ThreadLocal<PagingParams>();

    Response<User> getUsers();

    Response<Item> getItems();

    Response<Item> getItems(ItemType type);

}

然后客户可以做这样的事情

HszService.PAGING_PARAMS.set(new PagingParams(1, 10));
HszService hszService = .....; // obtain a ref somehow
hszService.getUsers();

然后,HszService应确保消耗ThreadLocal(也已删除)

public Response<User> getUsers(){
    PagingParams pageingParams = PAGING_PARAMS.get();
    PAGING_PARAMS.remove();

    ....
}

就像我在回答的开头所说:&#34; API是间接的&#34;因此容易出错:

  • 在调用其中一个方法之前,客户端可能忘记设置ThreadLocal
  • 或参数使用者(例如getUsers方法)可能忘记删除ThreadLocal。因为线程经常从池中借用。然后,另一个调用可能仍然使用之前设置的ThreadLocal值。

答案 2 :(得分:0)

我上面的评论仍然有效,但我想出了一个非常难看的解决方案:

public interface HszService {

    Response<User> getUsers(int... pageParams);

    Response<Item> getItems(int... pageParams);

    Response<Item> getItems(ItemType type, int... pageParams);
}

当然,你必须写一些关于那些参数的评论,这些评论是0或2。而且你的实现可能会变得丑陋。

答案 3 :(得分:0)

我之前使用ThreadLocal方法回答的另一种方法是扩展Response对象。 e.g。

public interface Response<T> {
   public List<T> getObjects();   
   public List<T> getObjects(int page, int pageSize);
}

然后将服务实现更改为类似的内容。

public class HszServiceImpl implements HszService {

   public Response<User> getUsers(){
       return new Response<User>(){

              public List<T> getObjects(){
                  // move the old getUsers code here
              }

               public List<T> getObjects(int page, int pageSize){
                  // implement paging support
               }
       };
   }

}

但这可能仅在Response不能为Serializable时才有效。