public
Created

Second alternative to the standard Builder pattern implementation in Java. Also see blogpost at http://branchandbound.net/blog/java/2013/10/failed-experiment-improving-builder-pattern/

  • Download Gist
PizzaOrderNewStyle.java
Java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
package net.branchandbound.builder;
 
public class PizzaOrderNewStyle {
 
private int size;
private boolean pepperoni;
private boolean chicken;
private boolean mushroom;
private boolean peppers;
private String cheese;
private String sauce;
private String orderFor;
 
private PizzaOrderNewStyle() {
// Prevent direct instantiation
}
 
public static Builder pizzaOrder(int size, String sauce, String orderFor) {
return new PizzaOrderNewStyle.Builder(size, sauce, orderFor);
}
 
public static class Builder {
private PizzaOrderNewStyle pizza = new PizzaOrderNewStyle();
 
public Builder(int size, String sauce, String orderFor) {
pizza.size = size;
pizza.sauce = sauce;
pizza.orderFor = orderFor;
}
 
public Builder withPepperoni() {
pizza.pepperoni = true;
return this;
}
 
public Builder withChicken() {
pizza.chicken = true;
return this;
}
 
public Builder withMushroom() {
pizza.mushroom = true;
return this;
}
 
public Builder withPeppers() {
pizza.peppers = true;
return this;
}
 
public Builder withCheese(String _cheese) {
pizza.cheese = _cheese;
return this;
}
 
public PizzaOrderNewStyle build() {
try {
return pizza;
}
finally {
// Invalidate this builder
pizza = null;
}
}
}
 
public int getSize() {
return size;
}
 
public boolean isPepperoni() {
return pepperoni;
}
 
public boolean isChicken() {
return chicken;
}
 
public boolean isMushroom() {
return mushroom;
}
 
public boolean isPeppers() {
return peppers;
}
 
public String getCheese() {
return cheese;
}
 
public String getSauce() {
return sauce;
}
 
public String getOrderFor() {
return orderFor;
}
 
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((cheese == null) ? 0 : cheese.hashCode());
result = prime * result + (chicken ? 1231 : 1237);
result = prime * result + (mushroom ? 1231 : 1237);
result = prime * result + ((orderFor == null) ? 0 : orderFor.hashCode());
result = prime * result + (pepperoni ? 1231 : 1237);
result = prime * result + (peppers ? 1231 : 1237);
result = prime * result + ((sauce == null) ? 0 : sauce.hashCode());
result = prime * result + size;
return result;
}
 
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
PizzaOrderNewStyle other = (PizzaOrderNewStyle) obj;
if (cheese == null) {
if (other.cheese != null)
return false;
} else if (!cheese.equals(other.cheese))
return false;
if (chicken != other.chicken)
return false;
if (mushroom != other.mushroom)
return false;
if (orderFor == null) {
if (other.orderFor != null)
return false;
} else if (!orderFor.equals(other.orderFor))
return false;
if (pepperoni != other.pepperoni)
return false;
if (peppers != other.peppers)
return false;
if (sauce == null) {
if (other.sauce != null)
return false;
} else if (!sauce.equals(other.sauce))
return false;
if (size != other.size)
return false;
return true;
}
 
}
PizzaOrderNewStyleTest.java
Java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
package net.branchandbound.builder.test;
 
import static net.branchandbound.builder.PizzaOrderNewStyle.pizzaOrder;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import net.branchandbound.builder.PizzaOrderNewStyle;
import net.branchandbound.builder.PizzaOrderNewStyle.Builder;
 
import org.junit.Test;
 
public class PizzaOrderNewStyleTest {
@Test
public void valuesShouldBeRetained() {
PizzaOrderNewStyle pizzaOrder =
pizzaOrder(10, "tomato", "Sander").withPepperoni().withMushroom()
.withCheese("parmesan").build();
assertEquals(10, pizzaOrder.getSize());
assertEquals("tomato", pizzaOrder.getSauce());
assertEquals("Sander", pizzaOrder.getOrderFor());
assertTrue(pizzaOrder.isPepperoni());
assertFalse(pizzaOrder.isChicken());
assertTrue(pizzaOrder.isMushroom());
assertFalse(pizzaOrder.isPeppers());
assertEquals("parmesan", pizzaOrder.getCheese());
}
@Test
public void testEqualsHashCode() {
PizzaOrderNewStyle a = getCorrectlyFilledBuilder().build();
PizzaOrderNewStyle b = getCorrectlyFilledBuilder().build();
assertEquals(a, b);
assertEquals(a.hashCode(), b.hashCode());
}
 
@Test
public void cannotBuildTwice() {
Builder builder = getCorrectlyFilledBuilder();
assertNotNull(builder.build());
assertNull(builder.build());
}
@Test(expected = NullPointerException.class)
public void cannotUseBuilderAfterBuild() {
Builder correctlyFilledBuilder = getCorrectlyFilledBuilder();
correctlyFilledBuilder.build();
correctlyFilledBuilder.withCheese("FAIL");
}
private Builder getCorrectlyFilledBuilder() {
return pizzaOrder(10, "tomato", "Sander").withPepperoni().withMushroom()
.withCheese("parmesan");
}
 
}

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.