3

I've just read a fantastic example of a builder pattern.

In my program I'm creating a series of playerCharacter entities, which can be constructed in various ways, with some compulsory fields and some that can be added on as extra or added latter on (after construction). So, after reading the above post, it seems as though I need a builder pattern.

Do I have the option of the builder and super class (here, in the example Pizza and builder) sharing some of the methods? Is there a neat, known solution to this?

For instance if, in the above example (of the pizza), at a later time we had a method of Boolean isPizzaCold() and void heatTo(int degrees) and we wanted the pizza to return false to start with, as it's 'built' hot, and later to let the pizza 'get cold', so that it cools. How would I do this such that they share the same methods?

[edit: as per Joeri's suggestion I've changed the method example.]

Community
  • 1
  • 1
AncientSwordRage
  • 7,086
  • 19
  • 90
  • 173

2 Answers2

1

I don't really see the relation between your question and the builder pattern. If you want a method setTemperature() and a method isCold(), just add them to the Pizza:

private static final int COLD_THRESHOLD = 40;
private int temperature = 70;

public void setTemperature(int temperature) {
    this.temperature = temperature;
}

public boolean isCold() {
    return temperature <= COLD_THRESHOLD;
}
JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
  • In the example show, builder is a nested abstract class, with no methods in the (super) pizza class. How can I get them to share a subset of methods? – AncientSwordRage Jul 24 '12 at 11:12
  • 1
    No. In the example shown, the Builder is a public static inner class, not abstract, and there is no super class: the Builder doesn't extend Pizza. And they don't share any method at all. The methods in the Pizza have just not been written to keep the example concise, but the Pizza should of course have methods, alse it doesn't serve any purpose. The fields of the builder are just copied to the fields of the Pizza at construction time. – JB Nizet Jul 24 '12 at 11:23
  • But what if I did want them to share methods (though perhaps here *Pizza* isn't, for once the best example) for whatever reason? – AncientSwordRage Jul 24 '12 at 12:54
  • Then it wouldn't be the builder pattern anymore. A builder is used to build another object. It's not an instance of the object it builds. – JB Nizet Jul 24 '12 at 13:13
  • But I could 'build' a pizza at a certain temperature, and then later on the pizza might get cold. They'd both have a setTemperature method for this functionality, correct? – AncientSwordRage Jul 24 '12 at 13:22
  • Yes. If you need to set the temperature at build time (and not use a default initial temperature), the builder needs a `setTemperature()`. And if the pizza can get colder after it's been constructed, it needs some method that changes its temperature. – JB Nizet Jul 24 '12 at 13:30
1

If you take the builder out of the class, it's still a builder. A builder is in the first place a convenient way to construct your object, it doesn't always need to be the only way. You could even state that creating an object is clearly a separate responsibility, and that it is cleaner to separate it (like a factory - builder pattern combined). I personally believe it depends mostly on the complexity of the creation.

No, your object and builder classes cannot share methods. The only way to share method is through inheritance, which clearly is not to be used here.

Your builder is a throwaway object, and the object it constructs is clearly of a different class. The only thing you can do is store the requested value, and call the appropriate setters automatically after the object was built.

void setTemperature(int t){
  this.temperature = t;
}

Pizza build() {
   Pizza pizza = new Pizza(... usual constructor stuff);
   pizza.setTemperature(temperature);
   return pizza;
}

Also, I wonder if void setTemperature(int) makes sense. void heatTo(int degrees) makes more sense to me :)

Joeri Hendrickx
  • 16,947
  • 4
  • 41
  • 53
  • How would I delegate methods? This sounds like the right thing. – AncientSwordRage Jul 24 '12 at 11:50
  • Sorry; not delegate methods; you couldn't use those since you don't have your object yet :) I updated the answer. – Joeri Hendrickx Jul 24 '12 at 12:26
  • Doesn't having break the pattern? I think your code is confusing me, is that a method in the `Builder` or the `Pizza` class? Why does it have a constructor attached to it? – AncientSwordRage Jul 24 '12 at 12:44
  • 1
    I adapted the answer to include the answer to 'does my builder have to be a separate class'. The constructor in the example above can be private (if the Builder is an inner class it can still invoke it). I like putting immutable fields in the constructor, because then you can make them final. You cannot do this if you just set them the regular way. If you take the builder out of the class, you will need a public constructor, but as long as it does not allow you to create an inconsistent object, that is not an issue. – Joeri Hendrickx Jul 24 '12 at 16:27