Question

This is the first time I am trying to make a factory.. please excuse me if I didn't use the pattern properly!

So this is my Factory:

public class BuilderFactory { 

    public BuilderFactory(){        
    }

    public <T extends Builder> T getBuilderOf(Object clazz){
        if(clazz instanceof House){             
            return (T) new HouseBuilder();
        }
        return null;
    }
}

it will return a builder (in this case HouseBuilder) which has a Builder interface.

Builder:

public interface Builder<T> {

    T build();

}

HouseBuilder:

public class HouseBuilder implements Builder<House> {

    private String street;

    public HouseBuilder() {

    }
    @Override
    public House build() {
        return new House(street);
    }

    @Override
    public HouseBuilder<House> withStreet(String street) {
        this.street = street;
        return this;
    }

}

This is the place where I call it:

BuilderFactory builderFactory = new BuilderFactory();

Now it is possible to do:

builderFactory.getBuilderOf(House.class).build();

Since build() is in the Builder interface. But if I want to do: builderFactory.getBuilderOf(House.class).withStreet("street");

I implicitily need to cast the builder like so:

 (HouseBuilder)builderFactory.getBuilderOf(House.class).withStreet("street")

Or else the compiler will complain.

I don't want to cast it, or instantiate my return value from the factory. Is there any option where I don't have to cast the result and could still use the .withStreet() method ? :)

Thanks in advance. Davey

Was it helpful?

Solution

Why bothering with the generics?

Your factory explicitly needs to know the concrete builder (return (T) new HouseBuilder()).

Your client explicitly needs to pass the correct type (House.class), and apparently you want it to know that type, because the client uses a method that is specific to the concrete builder (withStreet).

So just make the factory method concrete:

public HouseBuilder getHouseBuilder() {
    return new HouseBuilder();
}

OTHER TIPS

Since you are being very generic about your implementation if you want to add specifics you will need to be generic about those as well.

public interface Instruction {

    public String getDescription();
}

public StreetInstruction implements Instruction {
    String street;

    public StreetInstruction (String street) {
       this.street = street;
    }

}

public interface Builder<T> {

    T build(Instruction ... instructions);

}


builderFactory.getBuilderOf(House.class).build(new StreetInstruction("Sesame"));

Now there are many ways to go about this but this could be one of them. I think the problem that you are running into however is that different types of object are going to have very different implementations. So your factory the way you have it might also create furniture. If it did how would you instruct that builder you wanted a couch instead of a chair? There is nothing wrong with what you are going you just might want to think about your scope.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top