java nested builder pattern duplicate fields - java

The nested builder patterns that I've come across online usually have something like this:
class Person{
private int id;
private String name;
private int age;
... so on
private Person(Builder builder){
this.id = builder.id;
this.name = builder.name;
this.age = builder.age;
}
public static class Builder{
private int id;
private String name;
private int age;
... so on
public Builder id(int id){
this.id = id;
return this;
}
public Builder name(String name){
this.name = name;
return this;
}
.... so on
public Person build(){
return new Person(this);
}
}
}
My question is, is it necessary to duplicate fields in Person and Builder? It seems like a lot of redundant code. And my second question is, would the following code be a viable replacement, why or why not?
class Person{
private int id;
private String name;
private int age;
... so on
private Person(){}
public static class Builder{
private Person person = new Person();
public Builder id(int id){
this.person.id = id;
return this;
}
public Builder name(String name){
this.person.name = name;
return this;
}
.... so on
public Person build(){
return person;
}
// UPDATED -- another build method
public Person build(){
Person built = this.person;
this.person = new Person();
return built;
}
}
}
Note: I understand this topic may be opinionated and there may not be a "right" answer, but I just want to hear different ideas and opinions. I'm not looking for the ultimate truth.

Your code would be fine as long as:
you keep your Person member variables private (you are doing so)
you don't provide methods that allow modification of those member variables (the code you show does not do, but you have omitted parts of it)
those member variables are immutable or you ensure getters provide copies of them. usually better that the members are already immutable (hint: even java collections). otherwise you will be creating instances on each getX call.
once Builder.build is called, noone must be able to modify Person instance state, not even Builder itself. this is not happening in the code you posted
builder does not expose "temporal instance" being built (if any at all). No instance must be exposed aside the return of build method.
there are opinions about which is the preferred way or not, matter of taste most of the time. But in terms of being right or not, that approach would be fine with some modifications. At the end, what happens before the build is called is purely internal to the Builder. It's an implementation matter. The important thing is that the previous rules are met.
To fix rule 4: your Builder.build method should return a deep clone of the temp instance being used (there are ways to achcieve that without needing to specify each field). Or, you should have a flag in builder that forbids calling any other method on Builder instance, once build has been called.
Side note: i usually prefer that Builder class also uses private constructor. I would have this on Person class:
public static Builder builder() {
return new Builder();
}
This can give you more flexibility on the way to initialize the Builder, or even you can have several builder methods doing not exactly the same stuff in terms of "preconfiguring" the builder (and since they are methods, you have more flexibility on naming than on constructors :) )

Related

In Java is it correct to allow subclass to alter superclass private fields via public setter method?

Please look at the code below
Class Employee{
private String name;
private String id;
public String getName(){ return name; }
public void setName(String name){ this.name = name; }
public String getId(){ return id; }
public void setId(String id){ this.id = id; }
}
Class Teacher extends Employee{
private double salary;
}
Now my question is If I am creating an object of Teacher , then it does not make sense without the Teacher object having a name and id. I can set the same for teacher object via public setters of Employee but it it correct ?
Teacher t1 = new Teacher();
t1.setName("aaa");
t1.setId("224");
t1.salary = 200.00;
System.out.println(t1.toString());
I am asking this question as my understanding is if the field is private it should be used only via getters . But in the example provided above Teacher object will not make sense without having a Name or Id .
If it is correct then why not make the field public in the first place? What is the advantage in using it private and then allowing access via public setter ?
If it is not correct please provide an example of how the above Employee and Teacher class should be implemented ?
Your question seem to show a confusion between two concepts rather independant:
encapsulation
creation of objects
Encapsulation: it is better design to define private variables. Then you can not corrupt the object from outside. You must use setter to modify your employee.
But, if you trust Teacher, it could modify Employee as a subclass, without setter, it is faster to code (but little risky: if you have to change the setter in employee, Teacher wont get it, ...).
Creation of objects: you should pass certain values to the variables, or they are defined by default (or auto-built ...)
=> you can decide that Teacher have well defined values (default), or that you must give these values (mandatory). It is your design.
After that, you can change them directly or by setters of Employee (=> first concept of encapsulation).
then it does not make sense without the Teacher object having a name and id. I can set the same for teacher object via public setters of Employee but it it correct ?
This is where exactly constructor comes into picture. You need to pass them before you are using it.
Thumbrule : When you want something while building it, you need to force them to pass on constructor.

What is the best way to share only the getter methods to client?

I am writing an API with a class like this:
public class NKMPMission {
private String name;
private int age;
public NKMPMission(String name, int age)
{
this.name = name;
this.age = age;
}
public String getName()
{
return name;
}
public int getAge()
{
return age;
}
}
My Questions:
How can I make sure the user of this NKMPMission class accesses only the getters?
How can I introduce setters for this function so that I as a developer can set, but the user cannot set?
The usual way to do this is to not expose the class at all, just expose interfaces to that class. One interface for the general public and one for developers.
You then need a factory to create them.
/**
* Expose this interface to the public.
*/
public interface INKMPMission {
public String getName();
public int getAge();
}
/**
* Only expose this interface to developers.
*/
interface IDeveloperNKMPMission {
public void setName(String name);
public void setAge(int age);
}
public static class NKMPMissionFactory {
/**
* Expose only the INKMPMission construction.
*/
public INKMPMission make(String name, int age) {
return new NKMPMission(name, age);
}
/**
* Protected version for developers.
*/
IDeveloperNKMPMission forDeveloper(INKMPMission it) {
return IDeveloperNKMPMission.class.cast(it);
}
/**
* Private so no-one outside the factory knows about the inner workings.
*/
private static class NKMPMission implements INKMPMission, IDeveloperNKMPMission {
private String name;
private int age;
private NKMPMission(String name, int age) {
this.name = name;
this.age = age;
}
#Override
public String getName() {
return name;
}
#Override
public int getAge() {
return age;
}
#Override
public void setName(String name) {
this.name = name;
}
#Override
public void setAge(int age) {
this.age = age;
}
}
}
For the truly paranoid you can even use a proxy. This will make it difficult (but not impossible) to use the setters through reflection.
/**
* Expose only the INKMPMission construction.
*/
public INKMPMission make(String name, int age) {
return new NKMPMissionProxy(new NKMPMission(name, age));
}
/**
* Protected version for developers.
*/
protected IDeveloperNKMPMission forDeveloper(INKMPMission it) {
if (it instanceof NKMPMissionProxy) {
it = ((NKMPMissionProxy) it).theMission;
}
return IDeveloperNKMPMission.class.cast(it);
}
/**
* A proxy for the truly paranoid - makes using reflection more difficult (but not impossible)
*/
private static class NKMPMissionProxy implements INKMPMission {
private final NKMPMission theMission;
private NKMPMissionProxy(NKMPMission theMission) {
this.theMission = theMission;
}
#Override
public String getName() {
return theMission.getName();
}
#Override
public int getAge() {
return theMission.getAge();
}
}
1) How can i make sure user of this NKMPMIssion class access only getters.
You can't.
2) How can i introduce setters for this function so that as a developer i should be able to set, but the user should not be able to set.
It sounds like you're writing an API. If you return a NKMPMIssion instance from a public method of that API, the setters can be called. Even if you mark them private or protected, they can still be called via reflection. That said, usually making them non-public is sufficient. It does, at the very least, say "If you call these, you're in unsupported territory."
If you want to make it harder, you can return an instance that wraps a facade around the NKMPMIssion instance. But that just makes it harder, not impossible, since the facade instance has to have a reference to the NKMPMIssion instance, which (even if it's private) can be accessed via reflection.
The easiest thing is to make the API use the interface only and make the class an implementation detail.
public interface INKMPMission {
String getName();
int getAge();
}
public class SomeService{
private class MyNKMPMission implements INKMPMission {
//put getters and setters here
}
public List<INKMPMission> getMissions(){
//put some MyNKMPMissions in a list
}
}
Since MyNKMPMission is private the consumers will never be able do downcast and access the setters.
You can (in some kinda way), but you should not do it that way:
In each setter construct a new Exception
Inspect the generated Stacktrace
If the caller class is not within your package (or hardcode some direct classnames / methodnames) throw an IllegalAccessError
This way is neither pretty, nor fast as you have to check every single access to a setter.
Another way would be using the #CallerSensitive Annotation, though it's propritary API and is therefore not available on all plattforms / jre implementations: https://stackoverflow.com/a/22627383/1164913
The clean, and in most cases sufficent way would be using an Interface which only provides getters to the client, and returning that to the client.
It seems you trying to write an API. Assuming user means, developers who use your API.
In such cases, make the setter as protected and build some meaningful package structure, such that only child's and package members can see that.
If you want to protect that even from child's, there is no way other than making it private.
Answering the questions:
Q1. You can't as T.J. Crowder has said in his answer.
Q2. I would recommend you to try the following things in the following order from easiest to hardest, and take the option you consider the most suitable in terms of effort-return:
Have a look to: Java access modifiers.
Create an interface and expose that interface with the public methods to the "final" users of the "NKMPMission" class, as mentioned in Esben Skov Pedersen answer
Finally you can do the proxy approach mentioned in OldCurmudgeon answer
What I would do:
If your set of classes is going to be used internally then I would take option 1 combined with a good javadoc and project standards, it should be enough.
In case you are creating a public API I would take the option 2.
IMHO the option 3 adds too innecessary complexity in this case, and very few benefit, since every class method or attribute can be accessed anyway throw reflection (as many people has mentioned). I think everybody is aware about the fact that access throw reflection to API's hidden methods is hacky, dangerous and not convenient for the manteinance of the projects, due to API providers are in their right to change hidden methods implementations without further notification to the final users.

How to make object immutable in java

As this is a hot topic these days, I fail to understand certain concept. Please excuse me if I sound stupid but when I tried creating immutable object most of the posts I found following points
Make class final - makes sense
Dont allow mutators (setters) for the attributes - makes sense
Make attributes private - makes sense
Now I fail to understand why we need below points
Make constructor private and provide createInstance method with the same attributes as constructor or factory method ? How does it help ?
Make attributes final - post of the post fail to explain this point and some where I read to avoid the modification accidentally. How can you modify accidentally, when there are no mutators and class is final ? How making an attribute final is helping ?
Instead of factory pattern, can I use builder pattern ?
I am adding my class and test case here :
public final class ImmutableUser {
private final UUID id;
private final String firstName;
private final String lastName;
public ImmutableUser(UUID id, String firstName, String lastName) {
super();
this.id = id;
this.firstName = firstName;
this.lastName = lastName;
}
/**
* #return the id
*/
public UUID getId() {
return id;
}
/**
* #return the firstName
*/
public String getFirstName() {
return firstName;
}
/**
* #return the lastName
*/
public String getLastName() {
return lastName;
}
}
Test case
public class ImmutableUserTest {
#Test(expected = IllegalAccessException.class)
public void reflectionFailure() throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
ImmutableUser user = new ImmutableUser(UUID.randomUUID(), "john", "liu");
Field i =user.getClass().getDeclaredField("firstName");
i.setAccessible(true);
i.set(user, "cassandra");
System.out.println("user " + user.getFirstName()); // prints cassandra
}
}
This test case fails and prints cassandra.
Let me know if I am doing something wrong.
Make constructor private and provide createInstance method with the same attributes as constructor or factory method ? How does it helps ?
Answer: making the constructor private and providing createInstance() (factory method) does not help by itself: it is one of few things you should do in order to allow users to actually use the class and its instances while you still have the control of the way instances are created.
Make attributes final - the post fails to explain this point and somewhere I read to avoid the modification accidentally. How can you modify accidentally, when there are no mutators and class is final ? How making an attribute final is helping ?
Answer: declaring a class as final means that the user can't extend it, so it "blocks" the user from this kind of "workaround". Declaring an attribute as final won't allow the user of the class to change it. It cannot be "modified accidentally", but it can be "modified viciously" using reflection. Let's see an example, say you have:
final public class SomeClass {
final Integer i = 1;
}
from another class you can do as follows:
class AnotherClass {
public static void main (String[] args) throws Exception {
SomeClass p = new SomeClass();
Field i =p.getClass().getDeclaredField("i");
i.setAccessible(true);
i.set(p, 5);
System.out.println("p.i = " + p.i); // prints 5
}
}
Can instead of factory use builder pattern ?
Answer: you can use the builder pattern or any pattern that helps you control the creation of instances of the class.
Further:
If you want to make sure your class is immutable, make sure that any getter returns a deep-copy of the class member. This technique is called "protective/defensive copy". You can read more about it here
I'd start from making attributes final. Making attribute final guarantees that you cannot change the attribute value. I think this is obvious. (I will write additional comment to changing the content of references immutable objects later).
Now, when all your attributes are final they must be initiated via constructor. However some classes have a lot of attributes, so the constructor becomes huge. Moreover sometimes some attributes can be initialized to default values. Attempt to support this causes us to implement several constructors with almost random combination of arguments. However Builder pattern helps us. But how to make user to use Builder instead of direct invocation of constructor? The answer is making constructor private and creating static method that returns builder:
public class Person {
private final String firstName;
private final String lastName;
private final Person mother;
private final Person father;
private Person(String firstName, String lastName, Person mother, Person father) {
// init the fields....
}
public static PersonBuilder builder() {
return new PersonBuilder();
}
public static class PersonBuilder {
// here fields are NOT final
private String firstName;
private String lastName;
private Person mother;
private Person father;
public PersonBuilder bornBy(Person mother) {
this.mother = mother;
return this;
}
public PersonBuilder conceivedBy(Person father) {
this.father = father;
return this;
}
public PersonBuilder named(String firstName) {
this.firstName = firstName;
return this;
}
public PersonBuilder fromFamily(String lastName) {
this.lastName = lastName;
return this;
}
Person build() {
return new Person(name, lastName, mother, father);
}
}
}
And here is the typical usage pattern:
Person adam = Person.builder().named("Adam").build(); // no mother, father, family
Person eve = Person.builder().named("Eve").build(); // no mother, father, family
Person cain = Person.builder().named("Cain").conerivedBy(adam).bornBy(eve); // this one has parents
As you can see builder pattern often is better than factory because it is much more flexible.
I think that you missed one point in your question: references to other (mutable) objects. If for example we add field Collection<Person> children to our Person class we have to care that getChildren() returns either Iterable or at least unmodifirable collection.
Making the constructor private and using the builder pattern are not necessary for immutability. However because your class can't provide setters and if it has many fields, using a constructor with many parameters can be detrimental to readability hence the idea to use the builder pattern (which needs a pervade constructor).
The other answers seem to have missed an important point though.
Using final fields is essential, not only to ensure that they don't get modified, but because otherwise you lose some important thread safety guarantees. Indeed, one aspect of immutability is that it brings you thread safety. If you don't make the fields final your class becomes effectively immutable. See for example Must all properties of an immutable object be final?

Builder (Joshua Bloch-style) for concrete implementation of abstract class?

Let's say I have an abstract class (BaseThing). It has one required parameter ("base required") and one optional parameter ("base optional"). I have a concrete class that extends it (Thing). It also has one required parameter ("required") and one optional parameter ("optional"). So something like:
public abstract class BaseThing {
public static final String DEFAULT_BASE_OPTIONAL = "Default Base Optional";
private final String baseRequired;
private String baseOptional = DEFAULT_BASE_OPTIONAL;
protected BaseThing(final String theBaseRequired) {
this.baseRequired = theBaseRequired;
}
final void setBaseOptional(final String newVal) {
this.baseOptional = newVal;
}
public final void selfDescribe() {
System.out.println("Base Required: " + baseRequired);
System.out.println("Base Optional: " + baseOptional);
selfDescribeHook();
}
protected abstract void selfDescribeHook();
}
and:
public final class Thing extends BaseThing {
public static final String DEFAULT_OPTIONAL = "Default Optional";
private final String required;
private String optional = DEFAULT_OPTIONAL;
Thing(final String theRequired, final String theBaseRequired) {
super(theBaseRequired);
required = theRequired;
}
#Override
protected void selfDescribeHook() {
System.out.println("Required: " + required);
System.out.println("Optional: " + optional);
}
void setOptional(final String newVal) {
optional = newVal;
}
}
I want to have a Joshua Bloch-style builder for Thing objects. More generally, though, I want to make it easy for concrete implementations of BaseThing to have builders, so what I really want (I think) is a BaseThing builder that can easily be used to make a ThingBuilder, or an OtherThingBuilder, or a SuperThingBuilder.
Is there a better way than the following that I've come up with (or are there problems with what I've come up with)?
public abstract class BaseThingBuilder<T extends BaseThing> {
private String baseOptional = BaseThing.DEFAULT_BASE_OPTIONAL;
public BaseThingBuilder<T> setBaseOptional(final String value) {
baseOptional = value;
return this;
}
public T build() {
T t = buildHook();
t.setBaseOptional(baseOptional);
return t;
}
protected abstract T buildHook();
}
and:
public final class ThingBuilder extends BaseThingBuilder<Thing> {
private final String baseRequired;
private final String required;
private String optional = Thing.DEFAULT_OPTIONAL;
public ThingBuilder(final String theRequired,
final String theBaseRequired) {
required = theRequired;
baseRequired = theBaseRequired;
}
public ThingBuilder setOptional(final String value) {
optional = value;
return this;
}
protected Thing buildHook() {
Thing thing = new Thing(required, baseRequired);
thing.setOptional(optional);
return thing;
}
}
Which can be used to build Thing objects in a manner similarly to the following:
BaseThingBuilder<Thing> builder =
new ThingBuilder("Required!", "Base Required!")
.setOptional("Optional!")
.setBaseOptional("Base Optional!");
Thing thing = builder.build();
thing.selfDescribe();
Which outputs:
Base Required: Base Required!
Base Optional: Base Optional!
Required: Required!
Optional: Optional!
One issue that I know about, but that I don't consider particularly important (though if it can be improved it would be nice to do so) is that you have to set all non-base options before you set any base option: Doing otherwise would result in a syntax error, as setBaseOptional() returns a BaseThingBuilder rather than a ThingBuilder.
Thanks in advance.
I don't think it's a good idea to think of builders that way. A hierarchy of builders usually leads to headaches and fragile code.
Cutting down the amount of code that needs to be written in the concrete builders and reusing logic from the base builder is closely tied to the domain. It's not easy to develop a general solution. But, let's try to go through an example anyway:
public interface Builder<T> {
T build();
}
public class Person {
private final String name;
//the proper way to use a builder is to pass an instance of one to
//the class that is created using it...
Person(PersonBuilder builder) {
this.name = builder.name;
}
public String getName(){ return name; }
public static class PersonBuilder implements Builder<Person> {
private String name;
public PersonBuilder name(String name){ this.name = name; return this; }
public Person build() {
if(name == null) {
throw new IllegalArgumentException("Name must be specified");
}
return new Person(this);
}
}
}
Groovy, baby! Now what? Maybe you want to add a class to represent a student. What do you do? Do you extend Person? Sure, that's valid. How about taking a more "strange" route and attempting aggregation? Yep, you can do that too... Your choice would have an affect on how you will end up implementing builders. Let's say you stick to the traditional path and extend Person (you should already starting asking yourself, does it make sense for Person to be a concrete class? If I make it abstract, do I really need a builder? If the class is abstract should the builder be abstract?):
public class Student extends Person {
private final long id;
Student(StudentBulder builder) {
super(builder);
this.id = builder.id;
}
public long getId(){ return id; }
//no need for generics, this will work:
public static class StudentBuilder extends PersonBuilder {
private long id;
public StudentBuilder id(long id){ this.id = id; return this; }
public Student build() {
if(id <= 0) {
throw new IllegalArgumentException("ID must be specified");
}
return new Student(this);
}
}
}
Ok, this looks exactly like what you wanted! So, you try it:
Person p = new PersonBuilder().name("John Doe").build();
Student s = new StudentBuilder().name("Jane Doe").id(165).build();
Looks great! Except, it doesn't compile... There's an error at line 2 and it states The method id(int) is undefined for the type Person.PersonBuilder. The problem is that PersonBuilder#name returns a builder of type PersonBuilder, which isn't what you want. In StudentBuilder you actually want the return type of name to be StudentBuilder. Now, you think ahead and realize that if anything extends StudentBuilder you'd want it to return something else entirely... Is that doable? Yes, with generics. However, it's ugly as hell and introduces quite a bit of complexity. Therefore, I refuse to post the code that illustrates it, for the fear that someone will see this thread and actually use it in their software.
You might think rearranging method calls will work (calling id before calling name): new StudentBuilder().id(165).name("Jane Doe").build(), but it won't. At least not without an explicit cast to Student: (Student)new StudentBuilder().id(165).name("Jane Doe").build() since, in this case, PersonBuilder#build is being called which has a return type of Person... This is simply unacceptable! Even if it worked without an explicit cast, it should make you wince to know that a builder's methods must be called in a certain order. Because if you don't, something won't work...
There are many more problems that would arise if you continue trying to get it to work. And even if you did get it to work, I don't think it would be easily comprehensible and certainly not elegant. Of course, feel free to prove me wrong and post your solution here.
By the way, you should also ask yourself what is an abstract builder? Because, it sounds like an oxymoron.
In the end, I believe that the scope of this question is too great. The answer is domain-specific and hard to come up with in the absence of your requirements. Just remember, the general guideline for builders is to have them be as simple as possible.
Also, take a look at a related question.
As far as I can tell if you remove the generics then
BaseThingBuilder<Thing> builder =
new ThingBuilder("Required!", "Base Required!")
changes to
BaseThingBuilder builder =
new ThingBuilder("Required!", "Base Required!")
The rest of it all remains same, including the restriction that subclass has to be initialized first. So I really don't think this warrants use of generics. Maybe I am missing something.
I seem to remember something like this from Bjarne Stroustrup, long back...

Methods and Composition java

I have a facade engine with a method
getOwner()
I also have another class called Car and another caller Owner. Car class also has a getOwner() method while the Owner class contains the name, the cost of the car and the budget of the owner.
So I have a method to initialize the engine and this calls the constructor in the newCARengine class.
public static void iniEngine(String name, int cost) {
model = new newCARengine(name, cost);
}
Composition. The engine class has a car, and the car class has an owner. For me to successfully call the getOwner() method I need to use instance variables (class level variable) to hold a reference to the other object in order to call that method from that object.
MY ENGINE CLASS: [below]
public class engine{
private String name;
private int cost;
public Car car;
public engine(String name, int cost){
this.name = name;
this.cost = cost;
}
public Owner getOwner(){
return car.getOwner();
}
}
I'm referencing the Car class by using an instance variable for that class "public Car car;" which then allows me to use "car.getOwner();" method.
MY CAR CLASS: [below]
public class Car{
public Owner owner //instance variable to reference the owner class
public Owner getOwner(){
return owner;
}
}
Now i'm ready to go to the Owner class where the Owner object is created.
MY OWNER CLASS: [below]
public class Owner{
private String name;
private int cost;
private int budget;
public Owner (String name, int cost){
this.name = name;
this.cost = cost;
}
public Owner (String name, int cost, int budget){
this.name = name;
this.cost = cost;
this.budget = budget;
}
public String getName(){return name;}
public int getCost(){return cost;}
public int getBudget(){return budget;}
}
Now I am doing something wrong as when I run the iniEngine() method, I get a nullpointer exception and this I belive is a result of the object not being created. The error is generated from here:
return car.getOwner(); //from the ENGINE CLASS
I need to return an object as a result of my engine class. but the object is not getting created. Any assistance would be appreciated.
I reviewed your code several times. I don't understand where you associate an owner to a car.
This is what causes the NullPointerException
I suggest you provide a CTOR to Car that gets Owner as parameter and in addition, consider having a setCar method.
Consider using the following code for Car:
public class Car{
public class Car(Owner owner) {
this.owner = owner;
}
private Owner owner //instance variable to reference the owner class
public void setOwner(Owner owner) {
this.owner = owner;
}
public Owner getOwner(){
return owner;
}
}
Style note: in Engine, car should probably also be private, just like the other fields, with either a setter, or a constructor argument.
It seems like some of the fields are not getting set. One debugging "trick" I use in similar cases is to temporarily make the fields final, and see what the compiler complains about. For example, if anybody is setting engine.car, it would complain. In this case, that is a good thing - it should be complaining! And, if nobody is setting engine.car, that's a red flag as to where the NPE is coming from.
Alternatively, if you do have setters/getters, put breakpoints in them (or, if you prefer, add System.out.prints) to verify that they are getting called. Or, temporarily rename them (I add "xxx" to the beginning) to verify that the compiler complains, proving that somebody is calling them.
I never instantiated the objects and only delcared the variables.
By changing the constructor to
public Engine(String name, int cost) {
car = new Car(new Owner(name, cost));
}
This created the objects successfully which in turn allowed me to call the getOwner() method and not get any NullPointerExceptions. Must have missed this part somehow.

Categories

Resources