Reputation: 31
I'm trying to hide the class constructor outside of the package scope (along with a few other setters) and force a potential package user to get this particular class only through its builder (for clarity and validation reason).
So far I've been achieving this goal by putting that class and its builder to the same package and declaring package visibility for all methods I'd like to hide. This however, has some downsides. It imposes more stiff package structure and limits the possibility to extend class builder by the user.
I'm curious about any alternative solution or pattern? I've heard a while ago rumors about introducing "module" visibility modifier to Java ( which I think would solve the problem ) but I guess they ditched that idea.
Upvotes: 1
Views: 438
Reputation: 147154
Firstly I suggest putting full validation (and copying of mutable values) in the product rather than trusting the client.
If you want to separate the builder interface that the client is using from the product, then add that layer of indirection.
Most simplistic is to have product expose a constructor with huge parameter list and performs the usual constructor responsibilities (copying mutable, validating arguments and ensuring that the object is initialised into a usable state). The builders can be in a different dependent package/module/jar/library and use the constructor interface.
So now we're back to big constructor. You can fix this in a number of ways. For instance you could have a canonical builder inside the same class/package/module, which other object can use.
Or you could have an interface with "get" methods (drop the get
prefix, it's pointless in a type of gets) replacing each parameter in the constructor. The product constructor now only needs a single argument and can pull each argument. Each builder can implement the interface as an anonymous inner class (say) when it is time to finish the product build.
Upvotes: 0
Reputation: 2174
Use a public Builder static inner class :
public class OuterClass{
private MyType1 field1;
private MyType2 field2;
private OuterClass(MyType1 field1, MyType2 field2){....}
public static class Builder{
private static final MyType1 DEFAULT_VALUE_1 = something;
private static final MyType2 DEFAULT_VALUE_2 = somethingelse;
private MyType1 field1=DEFAULT_VALUE_1;
private MyType2 field2=DEFAULT_VALUE_2;
public Builder() {...}
public setFiled1(MyType1 field1) { this.field1 = field1)
public setFiled2(MyType2 field2) { this.field2 = field2)
public OuterClass build() { return new OuterClass(field1,field2);}
}
}
for further robustness, make your field in the outerClass final
Upvotes: 0
Reputation: 94
I haven't worked that much with Java but I believe what you could do is declaring a static method that creates an instance of the class
public static build()
{
return new FilePro();
}
That way you could create a new instance of the class only from the same package and you could extend the class without any restrictions
Upvotes: 0
Reputation: 33534
- Use protected
access-modifier to restrict the access of the constructor code outside that package.
Eg:
public class FilePro {
protected FilePro(){ // This block is accessible only
// within this package
}
}
Upvotes: 1