休息客户设计决策

时间:2014-11-02 23:10:27

标签: java android design-patterns retrofit

我正在使用改造来开发休息客户端。其余服务器使用oauth作为身份验证。对于此任务,我不必关心令牌过期。所以基本上我首先请求令牌,然后将其附加到所有后续调用。 截至目前,我正在使用两个班级。一个获取访问令牌,另一个获取其他所有内容。我想我想合并这两个......但我不知道该怎么做。

第一个类只有一个方法,它采用用户名和密码以及改进的回调接口。我喜欢回调的简单性,但想以某种方式抽象它,所以如果需要,我可以很容易地从改造改为其他东西。

public class RequestAccessToken implements IRequestAccessToken {
    private String username;
    private String password;

    private IRestAPI client;


    public RequestAccessToken()
    {
        RestAdapter restAdapter = new RestAdapter.Builder()
                .setEndpoint(Config.ENDPOINT)
                .build();
        client = restAdapter.create(IRestAPI.class);
    }

    @Override
    public void requestAccessToken(String username, String password, Callback callback) {
        String grantType = Config.grantType;
        String clientId = Config.clientId;
        String clientSecret = Config.clientSecret;

        client.getAccessToken(grantType, username, password, clientId, clientSecret, callback);
    }
}

第二个类将访问令牌作为构造函数参数,并将其附加到所有http请求。

public class RestClient implements IRestClient {
    private static final String TAG = RestClient.class.getSimpleName();
    private IRestAPI client;

    public RestClient(final String accessToken)
    {
        RequestInterceptor requestInterceptor = new RequestInterceptor()
        {
            @Override
            public void intercept(RequestFacade request) {
                request.addHeader("Authorization", "Bearer " + accessToken);
            }
        };

        RestAdapter restAdapter = new RestAdapter.Builder()
                .setEndpoint(Config.ENDPOINT)
                .setRequestInterceptor(requestInterceptor)
                .build();
        client = restAdapter.create(IRestAPI.class);
    }

    @Override
    public List<User> requestUsers() {
        return client.requestUsers();
    }

    @Override
    public List<Soemthing> requestSomething() {
        return client.requestSomething();
    }

    @Override
    public List<SoemthingElse> requestSomethingElse() {
        return client.requestSomethingElse();
    }
}

我希望得到一些关于如何更好地做到这一点的建议和建议,并且可能合并这两个类。我正在考虑将RequestAccessToken的requestAccessToken方法作为RestClient类的静态成员。至少那将合并两个类。但是我使用工厂来创建RestClient,如果我在其上声明一个静态方法,我在整个代码中使用它,我会得到紧密耦合...建议?

1 个答案:

答案 0 :(得分:0)

在其他地方讨论之后,我想出了以下代码。

public class RestClient implements IRestClient {
    private static final String TAG = RestClient.class.getSimpleName();
    private IRestAPI client;
    private String username;
    private String password;
    private RequestAccessToken requestAccessToken;
    private Access access;

    private static RestClient singleton;

    // TODO: use Dagger
    public static RestClient getInstance()
    {
        if(singleton == null)
        {
            singleton = new RestClient();
        }
        return singleton;
    }

    /**
     * Access declared as private to prevent instantiation outside of this class.
     */
    private RestClient()
    {
        requestAccessToken = new RequestAccessToken();
    }

    /**
     * Request an access token.
     *
     * @return A string containing the access token
     */
    public String requestAccessToken(String username, String password)
    {
        this.username = username;
        this.password = password;
        this.access = requestAccessToken.requestAccessToken(username, password);
        return this.access.getAccess_token();
    }

    /**
     * Wrapper for {@link #requestAccessToken(String, String) requestAccessToken}
     * @return
     */
    public String requestAccessToken()
    {
        if(username == null || password == null) {
            throw new IllegalArgumentException("missing user/pass");
        }
        return requestAccessToken(username, password);
    }

    /**
     * Eventually we want to look at Access.getExpires_in() and return weather or not the token is
     * expired.
     *
     * @return value indicating weather or not the token is expired.
     */
    public boolean isAccessTokenExpired()
    {
        return false;
    }

    /**
     * Return an instance of a rest client with a valid access token.
     * @return
     */
    private IRestAPI getClient()
    {
        if(access == null)
        {
            requestAccessToken();
        }
        if(isAccessTokenExpired())
        {
            // Refresh token
        }
        if(client == null) {
            RequestInterceptor requestInterceptor = new RequestInterceptor() {
                @Override
                public void intercept(RequestFacade request) {
                    request.addHeader("Authorization", "Bearer " + access.getAccess_token());
                }
            };

            RestAdapter restAdapter = new RestAdapter.Builder()
                    .setEndpoint(Config.ENDPOINT)
                    .setLogLevel(RestAdapter.LogLevel.FULL)
                    .setRequestInterceptor(requestInterceptor)
                    .build();
            client = restAdapter.create(IRestAPI.class);
        }
        return client;
    }

    /**
     * Login to the api and get a access token.
     *
     * @param username
     * @param password
     */
    @Override
    public void login(String username, String password)
    {
        Log.d(TAG, "login");
        requestAccessToken(username, password);
    }

    /**
     * Request a list of organizations.
     * @return List of Organizations.
     */
    @Override
    public List<Organization> requestOrganizations() {
        Log.d(TAG, "requestOrganizations");
        // TODO: error handling
        // TODO: caching... which isn't http
        return getClient().requestOrganizations();
    }

    // Add more api requests here

}