在这种情况下,单身人士,工厂还是其他更好的东西?

时间:2012-01-26 11:52:31

标签: java api design-patterns singleton

我正在努力找到最好的OO方式,我很感激你的帮助。

我认为最简单的方法是向您展示我是如何做到这一点并尝试解释我想要的东西(我简化它):

abstract public class MyServiceApi {
    private static MyServiceApi instance = null;

    public static <T extends MyServiceApi> T getInstance(Class<T> cls) {
        if (instance == null) {
            try {
                instance = cls.newInstance();
            }
            catch (InstantiationException e) {}
            catch (IllegalAccessException e) {}
        }

        return (T) instance;
    }

    private private HashMap<String, String> headers;

    protected MyServiceApi() {}

    public HashMap<String, String> getHeaders() {
        return headers;
    }

    public void setHeaders(HashMap<String, String> headers) {
        this.headers = headers;
    }

    protected <T extends IMyServiceApiResponse> T send(String url, IMyServiceApiRequest request, Class<T> to) {
        // Do some stuffs

        // IMPORTANT : Also set headers to the request
    }

    protected String getBaseUrl() {
        return "http://api.mywebsite.com/";
    }
}

public class UsersApi extends MyServiceApi {
    public static UsersApi getInstance() {
        return getInstance(UsersApi.class);
    }

    protected UsersApi() {
        super();
    }

    @Override
    protected String getBaseUrl() {
        return super().getBaseUrl() + "Users/";
    }

    // mutliple function that calls a specific URL in the API, and return specifics object based on the call, for example :
    public MyServiceApiUsersResponse getUsers(MyServiceApiUsersRequest request) {
        return send(getBaseUrl() + "get", request, MyServiceApiUsersResponse.class);
    }
}

public class ItemsApi extends MyServiceApi {
    public static ItemsApi getInstance() {
        return getInstance(ItemsApi.class);
    }

    protected ItemsApi() {
        super();
    }

    @Override
    protected String getBaseUrl() {
        return super().getBaseUrl() + "Items/";
    }

    // mutliple function that calls a speicfic URL in the API, and return specifics object based on the call, for example :
    public MyServiceApiItemsResponse getUsers(MyServiceApiItemsRequest request) {
        return send(getBaseUrl() + "get", request, MyServiceApiItemsResponse.class);
    }

}

既然你有这个想法,我就会陷入困境。

首先,我不知道我所做的是否正确(以Java OO方式)。我认为这不错,但我缺乏确定的经验。

其次,一旦我的项目运行,MyServiceApi将保留相同的标题,我将不会调用其他API或其他凭据。这就是我想到Singleton的原因:我在应用程序启动时设置了标题,然后我只需要执行请求。 但我认为让UsersApiItemsApi延长MyServiceApi是最好的方法。他们使用MyServiceApi,但他们没有扩展其功能。 另外,我认为SingleTon是反模式的,不适合测试等等。

所以现在我松了,我不知道该怎么办。你会怎么做?

一个可能的想法是删除MyServiceApi的摘要并在其上设置单例,使用UsersApiItemsApi来使用MyServiceApi但不要通过扩展它,但是那我怎么管理getBaseUrl呢?

非常感谢你的帮助,我真的很感激!

3 个答案:

答案 0 :(得分:2)

使用依赖注入而不是单例。

看起来您正在尝试使用具有基本URL并设置标头的单个服务。

使用依赖注入,创建一个名为MyApiService的服务,就像你拥有的一样,并且UsersApi和ItemsApi依赖于它,如下所示:

public class MyServiceApi {

    private final String baseUrl;
    private final HashMap<String, String> headers;

    protected MyServiceApi(String baseUrl, HashMap<String, String> headers) {
        this.baseUrl = baseUrl;
        this.headers = headers;
    }

    protected <T extends IMyServiceApiResponse> T send(String url,
            IMyServiceApiRequest request, Class<T> to) {
        // Do some stuffs

        // IMPORTANT : Also set headers to the request
    }

    protected String getBaseUrl() {
        return baseUrl;
    }
}

public class UsersApi {

    private final MyServiceApi myServiceApi;

    protected UsersApi(MyServiceApi myServiceApi) {
        this.myServiceApi = myServiceApi;
    }

    protected String getBaseUrl() {
        return myServiceApi.getBaseUrl() + "Users/";
    }

    // mutliple function that calls a specific URL in the API, and return
    // specifics object based on the call, for example :
    public MyServiceApiUsersResponse getUsers(
            MyServiceApiUsersRequest request) {
        return myServiceApi.send(getBaseUrl() + "get", request,
                MyServiceApiUsersResponse.class);
    }
}

您可以做的其他一些事情:

  • 如果要始终公开getBaseUrl,请创建MyServiceApi和UsersApi都实现的接口
  • 查看有关Dependency Injection的一些信息

答案 1 :(得分:1)

这就是我写它的方式

enum MyServiceApi {
    UsersApi {
        public MyServiceApiUsersResponse getUsers(MyServiceApiUsersRequest request) {
            return send(getBaseUrl() + "Users/get", request, MyServiceApiUsersResponse.class);
        }

    },  ItemsApi {
        // mutliple function that calls a speicfic URL in the API, and return specifics object based on the call, for example :
        public MyServiceApiItemsResponse getUsers(MyServiceApiItemsRequest request) {
            return send(getBaseUrl() + "Items/get", request, MyServiceApiItemsResponse.class);
        }
    };

    private final Map<String, String> headers = new LinkedHashMap<String, String>();

    public Map<String, String> getHeaders() {
        return headers;
    }

    public void setHeaders(HashMap<String, String> headers) {
        this.headers.clear();
        this.headers.putAll(headers);
    }

    public abstract <T extends IMyServiceApiResponse> T send(String url, IMyServiceApiRequest request, Class<T> to);

    protected String getBaseUrl() {
        return "http://api.mywebsite.com/";
    }
}

答案 2 :(得分:1)

这只是为了您的意识。如果您使用的是Singleton模式,则应同步getInstance方法。想想你运行多个线程的场景。例如,如果一个线程检查了实例是null,并且因为它是null,它将进入try块。让我们说它停止,第二个线程进入运行状态。仍然是实例为null,它也有机会进入try块。那么最终你将最终得到两个实例,而你的Singleton策略将会破解