Builder pattern with inheritance support generics issue - java

I implemented pattern based on this answer
I have the following asbtract config:
public abstract class AbstractConfig {
public static abstract class Builder<B extends Builder<B>> {
private int calories = 0;
public Builder() {
}
public B setCalories(int calories) {
this.calories = calories;
return (B) this;
}
public abstract AbstractConfig build();
}
private int calories = 0;
protected AbstractConfig(final Builder builder) {
calories = builder.calories;
}
}
And I have the following concrete config:
public class DialogConfig extends AbstractConfig {
public static class DialogConfigBuilder<B extends DialogConfigBuilder<B>> extends Builder<B> {
private double width;
private double height;
public DialogConfigBuilder() {
//does nothing.
}
public B setWidth(final double value) {
width = value;
return (B) this;
}
public B setHeight(final double value) {
height = value;
return (B) this;
}
public DialogConfig build() {
return new DialogConfig(this);
}
}
private final double width;
private final double height;
protected DialogConfig(final DialogConfigBuilder builder) {
super(builder);
width = builder.width;
height = builder.height;
}
public double getWidth() {
return width;
}
public double getHeight() {
return height;
}
}
And this is how I use it
DialogConfig config = new DialogConfig.DialogConfigBuilder()
.setWidth(0)
.setCalories(0)
.setHeight(0) //X LINE
.build();
At X line I get - Can't find symbol method setHeight. What is my mistake?
EDIT - I will have and a ExtendedDialogConfig that must extend DialogConfig and etc. I mean there will be other subclasses.

You would first change setCalories() to:
public Builder<B> setCalories(int calories) {
this.calories = calories;
return this;
}
to get rid of that cast and the warning. And now look at this closely. You return a Builder. This code doesn't know about future subclasses. It only returns an instance of that base builder.
As a consequence, when you have that chained call:
.setHeight(0) .build();
that would return that base builder. To then call build() - which would build an abstract configuration. But you want to assign that to a more specific DialogConfig. Thus the error.
A (ugly) workaround:
DialogConfig.DialogConfigBuilder<?> builder = new DialogConfig.DialogConfigBuilder<>().setHeight(0);
builder.setCalories(0);
...config = builder.build();
And a solution - by again reworking setCalories():
#SuppressWarnings("unchecked")
public <T extends B> T setCalories(int calories) {
this.calories = calories;
return (T) this;
}
Fixes the compile error; and allows chaining the setCalories() call as well. Final exercise of getting rid of the cast/suppress is left as exercise to the reader.
And for the record - the "complete" solution, including all adaptions to get rid of raw types and other warnings:
abstract class AbstractConfig {
public static abstract class Builder<B extends Builder<B>> {
private int calories = 0;
#SuppressWarnings("unchecked")
public <T extends B> T setCalories(int calories) {
this.calories = calories;
return (T) this;
}
public abstract AbstractConfig build();
}
private int calories = 0;
public int getCalories() { return calories; }
protected <B extends Builder<B>> AbstractConfig(final Builder<B> builder) {
calories = builder.calories;
}
}
final class DialogConfig extends AbstractConfig {
public static class DialogConfigBuilder<B extends DialogConfigBuilder<B>> extends Builder<B> {
private double width;
private double height;
public DialogConfigBuilder<B> setWidth(final double value) {
width = value;
return this;
}
public DialogConfigBuilder<B> setHeight(final double value) {
height = value;
return this;
}
public DialogConfig build() {
return new DialogConfig(this);
}
}
private final double width;
private final double height;
protected <B extends DialogConfigBuilder<B>> DialogConfig(final DialogConfigBuilder<B> builder) {
super(builder);
width = builder.width;
height = builder.height;
}
public double getWidth() { return width; }
public double getHeight() { return height; }
}
public class Builders {
public static void main(String[] args) {
DialogConfig config = new DialogConfig.DialogConfigBuilder<>().setHeight(0).setCalories(0).build();
System.out.println(config);
}
}

I found my mistake. This is how I used DialogConfigBuilder
DialogConfig config = new DialogConfig.DialogConfigBuilder()
.setWidth(0)
.setCalories(0)
.setHeight(0) //X LINE
.build();
This is how I should use DialogConfigBuilder
DialogConfig config = new DialogConfig.DialogConfigBuilder<>()
.setWidth(0)
.setCalories(0)
.setHeight(0) //X LINE
.build();
Pay attention to <> in the second case.

Related

I'm trying to understand the Building Pattern and I have trouble with the Director

I try to code a builder pattern for my better understanding. Mostly I relied on GOF and wikipedia.
So my Object is a house with required attribute area and some optional attributes (like windows, doors, rooms etc.)
I will show you the code. Now, I'm not really sure if its correct and I think I don't have a director? I don't get in which cases you need one and how it works.
This is my class house and the innerclass HouseBuilder
public class House {
//required
private final String area;
//optional
private int windows;
private int doors;
private int rooms;
//constructor with HouseBuilder
private House(HouseBuilder builder) {
this.windows = builder.windows;
this.doors = builder.doors;
this.rooms = builder.rooms;
}
public static class HouseBuilder {
//required
private String area;
//optional
private int windows;
private int doors;
private int rooms;
//constructor with required attributes
HouseBuilder(String area) {
this.area = area;
}
//optional attributes
public HouseBuilder windows(int windows) {
this.windows = windows;
return this;
}
public HouseBuilder doors (int doors) {
this.doors = doors;
return this;
}
//function for building
public Housebuild() {
return new House(this);
}
}
Now, I just got a class demo where I can build a house like that:
House house = new House.HouseBuilder("Downtown")
.doors(3).windows(2).build();
But this is not a director like in the books. Is my idea even correct? And why is that better than just using setters?
Thanks!
Your example illustrates classic builder. Director is something like an abstract builder, and in practise it is rarely used because the client class can handle that perfectly well. Example of a director in your case would be:
public class House
{
public final String area;
public windows;
public int doors;
public int rooms;
}
interface HouseBuilder
{
public HouseBuilder area();
public HouseBuilder windows();
public HouseBuilder doorsors();
public HouseBuilder rooms();
public House build();
}
public static class DowntownHouseBuilder implements HouseBuilder
{
House downtownHouse = new House();
public HouseBuilder area()
{
downtownHouse.area = "Downtown";
}
public HouseBuilder windows()
{
downtownHouse.windows = 3;
return this;
}
public HouseBuilder doors()
{
downtownHouse.doors = 2;
return this;
}
public HouseBuilder rooms()
{
downtownHouse.rooms = 2;
return this;
}
public House build()
{
return downtownHouse;
}
}
public static class VilaBuilder implements HouseBuilder
{
House vila new House();
public HouseBuilder area()
{
vila.area = "Downtown";
}
public HouseBuilder windows()
{
vila.windows = 24;
return this;
}
public HouseBuilder doors()
{
vila.doors = 5;
return this;
}
public HouseBuilder rooms()
{
downtownHouse.rooms = 10;
return this;
}
public House build()
{
return vila;
}
}
class Driector
{
private HouseBuilder houseBuilder;
public Driector(HouseBuilder houseBuilder)
{
this.houseBuilder = houseBuilder;
}
public House buildHouse()
{
return this.houseBuilder.area()
.windows()
.doors()
.rooms()
.buid();
}
}
class HouseConstruction
{
public static void main(String[] args)
{
Director director = new Director(new VilaBuilder());
House house = director.buildHouse();
System.out.println("Builder constructed: "+ house);
}
}
Hope this helps clarify what is a Director in Builder pattern.

how to new an unknown object in abstract class

I would like to use a builder pattern to create an unknown object
how to do that?
my code like this:
public abstract class abstractA<T extends GameApplication<T>>{
public static class Builder<T> {
private JPanel panel = new JPanel();
private JFrame frame = new JFrame();
private int height = 0, width = 0;
private int x = 0,y = 0;
private Color backgroundColor = Color.BLUE;
public Builder setFrameHeightWidth(int height, int weight) {
this.height = height;
this.width = weight;
return this;
}
public Builder setLocation(int x, int y) {
this.x = x;
this.y = y;
return this;
}
public Builder setbackground(Color color) {
this.backgroundColor = color;
return this;
}
public T Build(){
//error here
return new T ;
}
}
I want to use it like this:
class RealA extends abstractA{
public static void main(String[] argv){
RealA a = abstractA.builder
.setLocation(100,200)
.setFrameHeightWidth(500,600)
.build();
}
}
and I can't create a generics object, but I need this. How to do that?
You can sort of do (something like) this if you let the builder know the kind of thing it is building (by passing it a class) and then get it to create the instance using reflection (e.g. the classes newInstance method).
This assumes all sub classes have a zero-argument constructor. (It can be modified to use a constructor with arguments, but each sub-class would need a constructor with the same signature)
For example...
public class Stack {
static abstract class Common {
protected String name;
public void setName(String name) {
this.name = name;
}
public abstract void doSomething();
}
static class Solid1 extends Common {
#Override
public void doSomething() {
System.out.println("Solid1's implementation: name=" + name);
}
}
static class Solid2 extends Common {
#Override
public void doSomething() {
System.out.println("Solid2's implementation: name=" + name);
}
}
static class Builder<T extends Common> {
private final Class<T> clazz;
private String name;
public Builder(Class<T> clazz) {
this.clazz = clazz;
}
public Builder<T> setName(String name) {
this.name = name;
return this;
}
public T build() {
T t;
try {
t = clazz.newInstance();
} catch (Exception e) {
throw new RuntimeException("Bad things have happened!");
}
t.setName(name);
return t;
}
}
public static void main(String[] args) {
Solid1 solid1 = new Builder<>(Solid1.class).setName("[NAME]").build();
Solid2 solid2 = new Builder<>(Solid2.class).setName("[NAME]").build();
solid1.doSomething();
solid2.doSomething();
}
}
Output...
Solid1's implementation: name=[NAME]
Solid2's implementation: name=[NAME]
Not sure how useful this is...

get some object of one class and use in another class

I want to use some object of one class and use in other class,but i can not
for example :
class 1:
public class Value {
private double radious;
private double lenght;
public void setRadious(double radious) {
this.radious = radious;
}
public void setLenght(double lenght) {
this.lenght = lenght;
}
}
question : how can I use just radious of class 1 in class 2???
class 2:
public class calculateArea
{
private Value value;
public double area()
{
return 3.14*radious*radious;
}
}
Create getters for both the values and access them in your second class.
Something like
public double getRadious() {
return this.radious;
}
public double getLenght() {
return this.lenght;
}
When working on OOP, ask yourself what code goes where and how many classes you have to make?
For your scenario, you can use aggregation or composition which is to declare the object of one class in another and then you can call the methods of the declared object using dot notation with getter setter methods. So it will go like this.
public class Value
{
private double radious;
private double lenght;
public void setRadious(double radious)
{
this.radious = radious;
}
public double getRadious() {
return this.radious;
}
public double getLenght() {
return this.lenght;
}
public void setLenght(double lenght)
{
this.lenght = lenght;
}
}
Class # 2
public class calculateArea
{
private Value value = new Value();
public calculateArea(double rad) {
value.setRadius(rad);
}
public double area()
{
return 3.14*value.getRadious()*value.getRadious();
}
}
Also, you need to set the value of radius before using it.
Make a getter Method for radious:
public double getRadious(){
return radious;
}
In the "Main Class":
Value v = new Value();
v.setRadious(2.5);/*Set the Radious value*/
public double area()
{
return 3.14*v.getRadious()*v.getRadious();
}
Add getters to class Value.
public class Value {
public double radious;
public double lenght;
public void setRadious(double radious) {
this.radious = radious;
}
public void setLenght(double lenght) {
this.lenght = lenght;
}
public double getLenght() {
return this.lenght;
}
public double getRadious() {
return this.radious;
}
}
Make an instance of class 1
public class calculateArea{
public Value;
calculateArea(){
value = new Value();
}
public double area(){
value.setRadious(2.34);//or set ACCORDINGLY
return 3.14 * value.radious * value.radious;
}
}
Declare getters and setters for Value-class:
public class Value {
private double radious;
private double lenght;
public Value(double radious, double length) {
this.radious = radious;
this.length = length;
}
public void setRadious(double radious) {
this.radious = radious;
}
public void setLenght(double lenght) {
this.lenght = lenght;
}
public double getRadious() {
return this.radious;
}
public double getLength() {
return this.length;
}
}
Instantiate the object with some variables:
Value value = new Value(2.0,3.0);
Add Constructor to CalculateArea class:
public class calculateArea {
private Value value;
public calculateArea(Value value) {
this.value = value;
}
public double area()
{
return 3.14*value.getRadious()*value.getRadious();
}
}
Instantiate:
calculateArea cArea= new calculateArea(value);
And print result to console in main() method:
System.out.println(cArea.area());

Shadowed Final Fields

So i am trying to generate a house(at this point a very simple house) and I have this Class:
public class Probability {
public final int MinWindows = 0;
public final int MaxWindows = 0;
//double values represend the percent chance for a specific attribute to
//generate
public final double hasBackDoor = 0;
public final double hasSecondFloor = 0;
public final double hasChimny = 0;
public final double hasGarage = 0;
public final double hasPorch = 0;
}
This class is then inherited by subclasses for different types of houses:
public class LowClassHouseProbability extends Probability{
public final int MinWindows = 5;
public final int MaxWindows = 10;
public final double hasBackDoor = 55.0;
public final double hasSecondFloor = 10.0;
public final double hasChimny = 5.5;
public final double hasGarage = 30.0;
public final double hasPorch = 60.0;
}
public class MiddleClassHouseProbability extends Probability{
public final int MinWindows = 20;
public final int MaxWindows = 50;
public final double hasBackDoor = 80.0;
public final double hasSecondFloor = 70.0;
public final double hasChimny = 10.0;
public final double hasGarage = 90.0;
public final double hasPorch = 85.0;
}
public class UpperClassHouseProbability extends Probability{
public final int MinWindows = 50;
public final int MaxWindows = 100;
public final double hasBackDoor = 100.0;
public final double hasSecondFloor = 100.0;
public final double hasChimny = 80.0;
public final double hasGarage = 99.0;
public final double hasPorch = 100.0;
}
So all of the subclasses of Probability shadow all of its fields which in my opinioin looks sloppy and is kind of annoying to read, however i need them to extend Probability because it would make it easyer when i actually have to use the object, because it looks nicer doing this:
public class House {
public House(Probability prob){
}
}
Than if i did not have a Probability class and did this:
public class House {
public House(LowClassHouseProbability prob){
}
public House(MiddleClassHouseProbability prob){
}
public House(UpperClassHouseProbability prob){
}
}
And this would only get worse with the more sub-classes that I create.
So my question is is there a better way of doing this that I'm not thinking of, or do i just have to do it one way or the other of the two solutions that I thought of.
Since you can not override fields from the super class in java those classes dont need at all to define the field..
public class LowClassHouseProbability extends Probability{
//public final int MinWindows = 50;
//public final int MaxWindows = 100;
those all are final declared so you need to set those in the constructor...
LowClassHouseProbability(int minW, int maxW,...){
super(minW, maxW, ....);
MiddleClassHouseProbability(int minW, int maxW,...){
super(minW, maxW, ....);
UpperClassHouseProbability(int minW, int maxW,...){
super(minW, maxW, ....);
and in the superclass Probability define the constructor:
Probability(int minW, int maxW,...){
MinWindows = minW;
MaxWindows = maxW;
// .... etc etc
It's probably best to remove the child classes altogether and define instances of the Probability class pertinent to your house types, and build a multi-argument constructor to facilitate instance construction.
Alternatively, you could refactor this into an interface:
public interface Probability {
int getMinWindwsMinWindows();
/*and so on*/
}
Then,
public class LowClassHouseProbability implements Probability{
{
#Override
int getMinWindwsMinWindows()
{
return 5;
}
/*and so on*/
}
The problem of managing constructors with too many fields can be solved by using a step builder. A step builder works by creating an interface for each step, then having the builder implement all of them. This way after completing each build step, only the next step is available to complete.
Here's an example:
package mcve;
public class Probability {
public final int minWindows;
public final int maxWindows;
public final double hasBackDoor;
public final double hasSecondFloor;
public final double hasChimny;
public final double hasGarage;
public final double hasPorch;
private Probability(final int minWindows,
final int maxWindows,
final double hasBackDoor,
final double hasSecondFloor,
final double hasChimny,
final double hasGarage,
final double hasPorch) {
this.minWindows = minWindows;
this.maxWindows = maxWindows;
this.hasBackDoor = hasBackDoor;
this.hasSecondFloor = hasSecondFloor;
this.hasChimny = hasChimny;
this.hasGarage = hasGarage;
this.hasPorch = hasPorch;
}
public static final Probability LOW_CLASS =
builder().setMinWindows(5)
.setMaxWindows(10)
.setHasBackDoor(55.0)
.setHasSecondFloor(10.0)
.setHasChimny(5.5)
.setHasGarage(30.0)
.setHasPorch(60.0)
.build();
// public static final Probability MIDDLE_CLASS = ...;
// public static final Probability UPPER_CLASS = ...;
public static MinWindowsStep builder() {
return new Builder();
}
public interface MinWindowsStep { MaxWindowsStep setMinWindows(int n); }
public interface MaxWindowsStep { HasBackDoorStep setMaxWindows(int n); }
public interface HasBackDoorStep { HasSecondFloorStep setHasBackDoor(double n); }
public interface HasSecondFloorStep { HasChimnyStep setHasSecondFloor(double n); }
public interface HasChimnyStep { HasGarageStep setHasChimny(double n); }
public interface HasGarageStep { HasPorchStep setHasGarage(double n); }
public interface HasPorchStep { BuildStep setHasPorch(double n); }
public interface BuildStep { Probability build(); }
private static final class Builder
implements MinWindowsStep,
MaxWindowsStep,
HasBackDoorStep,
HasSecondFloorStep,
HasChimnyStep,
HasGarageStep,
HasPorchStep,
BuildStep {
private int minWindows;
private int maxWindows;
private double hasBackDoor;
private double hasSecondFloor;
private double hasChimny;
private double hasGarage;
private double hasPorch;
#Override
public MaxWindowsStep setMinWindows(int minWindows) {
this.minWindows = minWindows;
return this;
}
#Override
public HasBackDoorStep setMaxWindows(int maxWindows) {
this.maxWindows = maxWindows;
return this;
}
#Override
public HasSecondFloorStep setHasBackDoor(double hasBackDoor) {
this.hasBackDoor = hasBackDoor;
return this;
}
#Override
public HasChimnyStep setHasSecondFloor(double hasSecondFloor) {
this.hasSecondFloor = hasSecondFloor;
return this;
}
#Override
public HasGarageStep setHasChimny(double hasChimny) {
this.hasChimny = hasChimny;
return this;
}
#Override
public HasPorchStep setHasGarage(double hasGarage) {
this.hasGarage = hasGarage;
return this;
}
#Override
public BuildStep setHasPorch(double hasPorch) {
this.hasPorch = hasPorch;
return this;
}
#Override
public Probability build() {
return new Probability(minWindows,
maxWindows,
hasBackDoor,
hasSecondFloor,
hasChimny,
hasGarage,
hasPorch);
}
}
}
Fields have to be assigned by name, and if you forget which step you are on, the compiler error will tell you:
// This will cause an error with a message something like
// "Cannot find symbol method build() in interface MinWindowsStep".
Probability p = Probability.builder()
.build();
If it turns out that it really is the case that you need to use inheritance, the builder pattern can be adapted to that by having e.g. an abstract build step with multiple implementations.

Java type parameter is not within its bound

I have a class Zeitpunkt which implements a date with time and in addition a class Suchbaum which represents a binary search tree.
I want to use a Comparator-Object in Suchbaum to sort a tree by the day of Zeitpunkt, but when I want to create a Suchbaum object, it prints the named error.
Zeipunkt
public class Zeitpunkt<T> implements Comparable<T>
{
private int jahr;
private int monat;
private int tag;
private int stunden;
private int minuten;
private double sekunden;
public int vergleich(Zeitpunkt a) { ... }
#Override
public int compareTo(T o) {
if(o instanceof Zeitpunkt)
return vergleich((Zeitpunkt)o);
return 0;
}
...
}
Suchbaum
public class Suchbaum<T extends Comparable<T>> {
private class Element {
private T daten;
private Element links;
private Element rechts;
public Element(T t) {
daten = t;
links = null;
rechts = null;
}
}
private Element wurzel;
private Comparator<T> comp;
...
}
Testclass
public class BaumTest {
public static void main(String[] args) {
// error in the following line (IntelliJ underlines the first
// "Zeitpunkt"). Suchbaum<Zeitpunkt<?>> = ... doesn't work either..
// *Completely confused*
Suchbaum<Zeitpunkt> sb = new Suchbaum<>((Zeitpunkt z1, Zeitpunkt z2) -> {
if(z1.getTag() > z2.getTag())
return 1;
else if(z1.getTag() == z2.getTag())
return 0;
else
return -1;
});
}
}
Any ideas? (the other threads with this topic didn't help me out)
Seems that you don't want to make your Zeitpunkt class parametrized, you just want it to implement Comparable interface. So change it like this:
public class Zeitpunkt implements Comparable<Zeitpunkt> {
private int jahr;
private int monat;
private int tag;
private int stunden;
private int minuten;
private double sekunden;
public int vergleich(Zeitpunkt a) {
return 0;
}
#Override
public int compareTo(Zeitpunkt o) {
return vergleich(o);
}
}
Also you need to define a constructor in your Suchbaum class:
public Suchbaum(Comparator<T> comp) {
this.comp = comp;
}

Categories