Why would we need the director pattern? The builder can itself execute the whole construction process instead of going through the director.

class Pizza {
 
	private String dough = "";
 
	private String sauce = "";
	private String topping = "";
 
	public static abstract class Builder {
 
		private Pizza pizza;
 
		public Builder() {
			pizza = new Pizza();
		}
 
		public abstract Builder buildDough();
 
		public abstract Builder buildSauce();
 
		public abstract Builder buildTopping();
 
		public Pizza getPizza() {
			return pizza;
		}
 
		protected void addTopping(String topping) {
			pizza.topping = topping;
		}
 
		protected void addSauce(String string) {
			pizza.sauce = string;
		}
 
		public void addDough(String dough) {
			pizza.dough = dough;
		}
	}
}
 
class SpicyPizzaBuilder extends Pizza.Builder {
 
	@Override
	public SpicyPizzaBuilder buildDough() {
		super.addDough("Pan Baked");
		return this;
	}
 
	@Override
	public SpicyPizzaBuilder buildSauce() {
		super.addSauce("hot");
		return this;
	}
 
	@Override
	public SpicyPizzaBuilder buildTopping() {
		super.addTopping("pepperoni+salami");
		return this;
	}
 
}
 
class HawaiianPizzaBuilder extends Pizza.Builder {
 
	@Override
	public Builder buildDough() {
		super.addDough("cross");
		return this;
	}
 
	@Override
	public Builder buildSauce() {
		super.addSauce("mild");
		return this;
	}
 
	@Override
	public Builder buildTopping() {
		super.addTopping("ham+Pineabble");
		return this;
	}
 
}
 
class Cook {
 
	private Pizza.Builder pizzaBuilder;
 
	public void constructPizza() {
		pizzaBuilder.buildDough().buildSauce().buildTopping();
	}
 
	public Pizza getPizza() {
		return pizzaBuilder.getPizza();
	}
 
	public void setPizzaBuilder(Builder hawaiianPizzaBuilder) {
		pizzaBuilder = hawaiianPizzaBuilder;
 
	}
}
 
public class BuilderExample {
 
	public static void main(String[] args) {
		Pizza.Builder hawaiianPizzaBuilder = new HawaiianPizzaBuilder();
		Pizza.Builder spicyPizzaBuilder = new SpicyPizzaBuilder();
 
		Cook cook = new Cook();
		cook.setPizzaBuilder(hawaiianPizzaBuilder);
 
		cook.constructPizza();
 
		Pizza hawaiian = cook.getPizza();
 
		cook.setPizzaBuilder(spicyPizzaBuilder);
		cook.constructPizza();
 
		Pizza spicy = cook.getPizza();
	}
 
}

In the above example the builder class have all the elements (data/method members) to construct the pizza ie PizzaBuilder is knowledgeable and highly coupled with the pizza. Then why the need for an extra layer of complexity? So construct method could be moved from cook (director) into PizzaBuilder.

Dani AI

Generated

Short answer: you don’t need a Director for your pizza example — the Director is a convenience for some situations, not a strict requirement of the pattern. Many modern write‑ups treat the Director as optional: it simply encapsulates a particular construction sequence so clients don’t have to call builder steps directly. (refactoring.guru)

Why the Director exists: it defines and reuses the ordering of build steps and hides that ordering from clients. That’s useful when the same construction algorithm must be applied to multiple builders (different representations) or when you want named, reusable build routines. At the same time, core sources and Java practice show builders that expose a fluent API (or Bloch’s static nested Builder) without any Director — so omitting the Director is common and often cleaner. (refactoring.guru)

Practical guidance: if the only place you ever call the steps is one client invocation (your main or Cook), move the sequence into the client or into the builder (fluent build()), and keep the code simple. If you find duplicate construction sequences across code paths, or you need to switch algorithms independently of representation, factor that sequence into a Director. In Java you’ll typically choose:

// Director style
director.setBuilder(builder);
director.construct();
product = builder.getProduct();

// Fluent/builder-as-factory
product = new Product.Builder()
           .withA(...)
           .withB(...)
           .build();

Both approaches are valid; prefer the fluent builder for immutable final objects and when client control is desirable. (baeldung.com)

Rule of thumb for and everyone here: don’t add a Director just because the pattern shows one. Start with the simplest readable design (your builder or client doing the sequence). Introduce a Director only when it buys you reuse, clearer responsibility boundaries, or easier testing. As hinted, sometimes the pattern really is “just a function” — and that’s perfectly fine. (refactoring.guru)

This is an excellent example of the retardedness and overcategorization of design patterns.

The "builder" is just a function.

The "director" is the thing that uses that function.

So this "design pattern" is just fancy way of describing one particular case where you use the behavior of one function to parameterize the behavior of another function. Big deal.

> Then why the need for an extra layer of complexity? So construct method could be moved from cook (director) into PizzaBuilder.

You could. And that would also be the right thing to do in this case.

You have to understand that the people who write design patterns articles on Wikipedia aren't the brightest people in the world.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.