patternjavaMinor
Java API without exposing implementation details
Viewed 0 times
withoutexposingjavadetailsimplementationapi
Problem
I am creating an API for consumption by other developers to interface with an internal framework. My goal is to be able to have the developers type something like:
or
The internal framework has all preferences persisted in the same manner. A user profile can be either a set of preferences specific to them (UserPreference) or a relation to a group preference using an ID (GroupPreference).
An example of current API usage:
I handle saving of the preference information through a PreferenceManager as a part of updating the overall profile:
Now for the questions:
```
public abstract class Preference {
/**
* Provides access to DashboardOptions object to manage what options are enabled
* and disabled on the users dashboard.
*
* @return DashboardOptions object
*/
public abstract DashboardOptions getDashboardOptions();
/**
* Gets the default inbox f
profile.setPreference(new GroupPreference(id));or
UserPreference preference = new UserPreference();
preference.setDefaultInbox("nameOfInbox");
// set any other options, classes simplified
profile.setPreference(preference);The internal framework has all preferences persisted in the same manner. A user profile can be either a set of preferences specific to them (UserPreference) or a relation to a group preference using an ID (GroupPreference).
An example of current API usage:
// Context object
Profile profile = userService.getProfile("accountName");
// Preference returned here is immutable
Preference preference = profile.getPreference();
preference.getDashboardOptions();
preference.getDefaultInbox();
// etc..
// To modify a users preferences
UserPreference userPreference = new UserPreference(preference);
userPreference.setDefaultInbox("newInbox");
// etc..
profile.setPreference(userPreference);
// Or to link it to a group preference
profile.setPreference(new GroupPreference(groupPreferenceId));I handle saving of the preference information through a PreferenceManager as a part of updating the overall profile:
preferenceManager.savePreference(preference, profileContext);Now for the questions:
- The protected save method feels extremely cludgy but I didn't want to have any methods in the interface that potentially exposes implementation details. Is there a better way?
- How is this design overall? Something need to be reorganized?
```
public abstract class Preference {
/**
* Provides access to DashboardOptions object to manage what options are enabled
* and disabled on the users dashboard.
*
* @return DashboardOptions object
*/
public abstract DashboardOptions getDashboardOptions();
/**
* Gets the default inbox f
Solution
Your
Your users will only ever get the
Update
Looking at it again it don't really see the point of the
Preference class really looks like it should be an interface. And in fact it is actually two interfaces: The public one for the user and the internal one for the manager. So I'd suggest you split it up:public interface Preference {
/**
* Provides access to DashboardOptions object to manage what options are enabled
* and disabled on the users dashboard.
*
* @return DashboardOptions object
*/
DashboardOptions getDashboardOptions();
/**
* Gets the default inbox for the user.
*
* @return Default inbox
*/
String getDefaultInbox();
}
interface SaveablePreference extends Preference // package private
{
/**
* Method that will be overridden to handle saving of the preference.
*
* @param profile ProfileContext passed in to provide information when saving preferences
* @param service PreferenceService object that handles saving of preferences
*/
void save(ProfileContext profile, PreferenceService service);
}Your users will only ever get the
Preference but your implementations (UserPreference and GroupPreference) will implement SaveablePreference.Update
Looking at it again it don't really see the point of the
PreferenceManager. If the user will have to call the manager in order to save the preference then why don't make the save method public in the first place - so you end up with only one interface. Then the user can call preference.save(context, service) (the arguments he'd have to supply anyway when calling the manager).Code Snippets
public interface Preference {
/**
* Provides access to DashboardOptions object to manage what options are enabled
* and disabled on the users dashboard.
*
* @return DashboardOptions object
*/
DashboardOptions getDashboardOptions();
/**
* Gets the default inbox for the user.
*
* @return Default inbox
*/
String getDefaultInbox();
}
interface SaveablePreference extends Preference // package private
{
/**
* Method that will be overridden to handle saving of the preference.
*
* @param profile ProfileContext passed in to provide information when saving preferences
* @param service PreferenceService object that handles saving of preferences
*/
void save(ProfileContext profile, PreferenceService service);
}Context
StackExchange Code Review Q#39982, answer score: 4
Revisions (0)
No revisions yet.