Builder Pattern

Builder pattern is a creational design pattern that allows you to separate the steps of creating a complex object from its representation.

Builder pattern is a creational design pattern whose main purpose is to separate the construction process of a complex object from its representation, so that objects with different representations can be created.

summary

intent

Separate a complex construction process from its representation, so that the same construction process can create different representations.

Mainly Solves

In software systems, the creation of a complex object usually consists of multiple parts; the combinations of these parts often change, but the combination algorithm is relatively stable.

When to Use

When some basic components remain unchanged, but their combinations change frequently.

How to Solve

Separate the changing and unchanging parts.

Key code

  • BuilderCreate and provide an instance.
  • director: Manage the dependencies of created instances and control the construction process.

Application example

  • At KFC, hamburgers, cola, fries, fried chicken wings, etc. are unchanged, but their combinations change frequently, producing different "combos".
  • In JavaStringBuilder。

Advantages

  • Separating the construction process from the representation makes the construction process more flexible and allows building different representations.
  • It can better control the construction process and hide specific construction details.
  • High code reusability; the same builder can be reused in different construction processes.

Disadvantages

  • If the product has few attributes, the builder pattern may lead to code redundancy.
  • Increases the number of classes and objects in the system.

Use Case

  • The object to be generated has a complex internal structure.
  • The internal attributes of the object to be generated are interdependent.

Notes

The difference from the factory pattern is that the builder pattern focuses more on the order of part assembly.

Structure

The builder pattern includes the following main roles:

  • Product: The complex object to be built. The product class usually contains multiple parts or attributes.

  • Abstract Builder: Defines the abstract interface for building the product, including methods for building the various parts of the product.

  • Concrete Builder: Implements the abstract builder interface, specifically determines how to build the various parts of the product, and is responsible for returning the final built product.

  • Director: Responsible for calling the builder's methods to construct the product. The director does not understand the specific construction process, only cares about the order and manner of product construction.

Implementation

Let's assume a business case for a fast food restaurant, where a typical combo can be a burger and a cold drink. The burger can be a Veg Burger or a Chicken Burger, and they are packed in a carton. The cold drink can be Coca-Cola (coke) or Pepsi (pepsi), and they are in bottles.

We will create an entity class representing food items (such as burgers and cold drinks).ItemInterface and implementationItemThe entity class of the interface, and an entity class representing food packaging.PackingInterface and implementationPackingThe entity class of the interface; burgers are packed in cartons, and cold drinks are in bottles.

Then we create aMealClass, withItemofArrayListand one by combiningItemto create different types ofMealObject'sMealBuilder。BuilderPatternDemoClass usageMealBuilderto create aMeal。

建造者模式的 UML 图

Step 1

Create an interface representing food items and food packaging.

Item.java

public interface Item { public String name(); public Packing packing(); public float price(); }

Packing.java

public interface Packing { public String pack(); }

Step 2

Create entity classes that implement the Packing interface.

Wrapper.java

public class Wrapper implements Packing { @Override public String pack() { return "Wrapper"; } }

Bottle.java

public class Bottle implements Packing { @Override public String pack() { return "Bottle"; } }

Step 3

Create an abstract class that implements the Item interface, which provides default functionality.

Burger.java

public abstract class Burger implements Item { @Override public Packing packing() { return new Wrapper(); } @Override public abstract float price(); }

ColdDrink.java

public abstract class ColdDrink implements Item { @Override public Packing packing() { return new Bottle(); } @Override public abstract float price(); }

Step 4

Create entity classes that extend Burger and ColdDrink.

VegBurger.java

public class VegBurger extends Burger { @Override public float price() { return 25.0f; } @Override public String name() { return "Veg Burger"; } }

ChickenBurger.java

public class ChickenBurger extends Burger { @Override public float price() { return 50.5f; } @Override public String name() { return "Chicken Burger"; } }

Coke.java

public class Coke extends ColdDrink { @Override public float price() { return 30.0f; } @Override public String name() { return "Coke"; } }

Pepsi.java

public class Pepsi extends ColdDrink { @Override public float price() { return 35.0f; } @Override public String name() { return "Pepsi"; } }

Step 5

Create a Meal class containing the Item objects defined above.

Meal.java

import java.util.ArrayList; import java.util.List; public class Meal { private List<Item> items = new ArrayList<Item>(); public void addItem(Item item){ items.add(item); } public float getCost(){ float cost = 0.0f; for (Item item : items) { cost += item.price(); } return cost; } public void showItems(){ for (Item item : items) { System.out.print("Item : "+item.name()); System.out.print(", Packing : "+item.packing().pack()); System.out.println(", Price : "+item.price()); } } }

Step 6

Create a MealBuilder class, the actual builder class responsible for creating Meal objects.

MealBuilder.java

public class MealBuilder { public Meal prepareVegMeal (){ Meal meal = new Meal(); meal.addItem(new VegBurger()); meal.addItem(new Coke()); return meal; } public Meal prepareNonVegMeal (){ Meal meal = new Meal(); meal.addItem(new ChickenBurger()); meal.addItem(new Pepsi()); return meal; } }

Step 7

BuiderPatternDemo uses MealBuilder to demonstrate the Builder Pattern.

BuilderPatternDemo.java

public class BuilderPatternDemo { public static void main(String[] args) { MealBuilder mealBuilder = new MealBuilder(); Meal vegMeal = mealBuilder.prepareVegMeal(); System.out.println("Veg Meal"); vegMeal.showItems(); System.out.println("Total Cost: " +vegMeal.getCost()); Meal nonVegMeal = mealBuilder.prepareNonVegMeal(); System.out.println("\n\nNon-Veg Meal"); nonVegMeal.showItems(); System.out.println("Total Cost: " +nonVegMeal.getCost()); } }

Step 8

Execute the program, output the result:

Veg Meal
Item : Veg Burger, Packing : Wrapper, Price : 25.0
Item : Coke, Packing : Bottle, Price : 30.0
Total Cost: 55.0


Non-Veg Meal
Item : Chicken Burger, Packing : Wrapper, Price : 50.5
Item : Pepsi, Packing : Bottle, Price : 35.0
Total Cost: 85.5

Related Articles

other extensions