The builder pattern is popular to create immutable objects, but there is some programming overhead to create a builder. So I wonder why not simply using a config object.
You should not use the public field, but protected or private. For accesing then you should use the getters and setter to keep the encapsulation..
You are losing several advantages of the builder pattern, as has already been pointed out (new is ugly and harder to maintain and leaking details compared to a clean builder).
The one I miss the most however is that the builder pattern can be used to provide what are called "fluent interfaces".
Instead of this:
ProductConfig config = new ProductConfig("Vodka");
config.alcohol = 0.38;
config.size = 0.7;
config.price = 17.99;
Product p = new Product(config);
You can do:
ProductFactory.create()
.drink("Vodka")
.whereAlcohoolLevelIs(0.38)
.inABottleSized(0.7)
.pricedAt(17.99)
.build();
Not everyone like fluent interfaces, but they are definitely a very nice use of the builder pattern (all fluent interfaces should use the builder pattern, but not all builder pattern are fluent interfaces).
Some great Java collections, like the Google collections, makes both very liberal and very good use of "fluent interfaces". I'd pick these any day over your "easier-to-type/less characters" approach : )
IMO, the builder pattern is much more roboust if you have things like validation, etc.
The builder pattern in your case can be changed to do the following:
Product p = new ProductBuilder("pName").alcohol(0.38).size(0.7).price(17.99).build();
The build()
method can do all the validation stuff that is needed for your builder.
The builder pattern also has several design advangates (all of which may not be applicable in your case). For deatils check this question