Reputation: 10341
I created a class (ProjectsDataAccess) that will handle access to the database, this is what the class can do:
This is the classes psudo code:
class ProjectsDataAccess {
public void addProject(Project project) {
// get the project data from the object and save it to the database
}
public void getProject() {
// get the project data from the database and return new project
//object with that data
}
}
And this is the project object:
class Project{
private String name;
private int id;
private Project(){}
Project(int id, String name){
this. id = id;
this.name = name;
}
Project(String name){
this. id = // generate id
this.name = name;
}
}
My issue is I dont want the user of the class to create object and supply its own ID using this constructor Project(int id, String name)
, but I only want the ProjectsDataAccess class to use it so it will be able to retrieve the data from the database (including the id) and then set it using the constructor. Is there a way I could change my design to do so.
Upvotes: 3
Views: 124
Reputation: 15250
A solution is to keep ProjectsDataAccess
and Project
classes in the same package and make constructor Project(int id, String name)
package visible (without any modifers, like it is now). The other constructor Project(String name)
needs to be public
to be visible for client code. And of course put client code in a different package.
package foo;
public class ProjectsDataAccess {
public void addProject(Project project) {
// get the project data from the object and save it to the database
}
public void getProject() {
// get the project data from the database and return new project
//object with that data
}
}
package foo;
public class Project {
private String name;
private int id;
private Project(){}
Project(int id, String name){
this. id = id;
this.name = name;
}
public Project(String name){
this. id = // generate id
this.name = name;
}
}
Upvotes: 1
Reputation: 39194
I suggest you to return a different interface to the user, only with the methods that the user is supposed to call.
For example:
interface UserProjectInterface
{
void AnyMethodUserIsSupposedToCall();
}
class Project implements ProjectUserInterface
{
//constructor won-t be no longer visible to the client class
public Project(){}
}
Then return only the interface:
class ProjectsDataAccess {
public void addProject(ProjectUserInterfaceproject);
public ProjectUserInterfacegetProject getProject() {
return new Project();
}
}
This pattern has several different advantages, since you are not exposing the concrete type to the client class.
EDIT:
If the user is supposed to create the UserProjectInterface you could use a factory (es. AbstractFactory), in order to encapsulated object creation:
interface AbstractProjectFactory
{
UserProjectInterface CreateProject();
}
and provide an implementation that instantiate your concrete object:
public AConcreteProjectFactory implements AbstractProjectFactory
{
public UserProjectInterface CreateProject()
{
return new Project();
}
}
An example of usage:
//client class:
AbstractProjectFactory factory = new AConcreteProjectFactory();
UserProjectInterface project = factory.CreateProject();
ProjectsDataAccess access = new ProjectsDataAccess();
access.addProject(project );
Upvotes: 0