DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Last call! Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • Object Relational Behavioral Design Patterns in Java
  • Distribution Design Patterns in Java - Data Transfer Object (DTO) And Remote Facade Design Patterns
  • Context Object Design Pattern in Java: Introduction and Key Points
  • Java: Object Pool Design Pattern

Trending

  • Teradata Performance and Skew Prevention Tips
  • Beyond Linguistics: Real-Time Domain Event Mapping with WebSocket and Spring Boot
  • How AI Agents Are Transforming Enterprise Automation Architecture
  • My LLM Journey as a Software Engineer Exploring a New Domain
  1. DZone
  2. Coding
  3. Languages
  4. Builder Design Pattern in Java

Builder Design Pattern in Java

By 
Brijesh Saxena user avatar
Brijesh Saxena
DZone Core CORE ·
Updated Oct. 15, 20 · Tutorial
Likes (8)
Comment
Save
Tweet
Share
10.8K Views

Join the DZone community and get the full member experience.

Join For Free

Here I am with my another article on design patterns - Builder Design Pattern. A very useful creational design pattern that lets us construct complex objects step by step.

Builder Design Pattern

  • The Builder design pattern is designed to provide a flexible solution to various object creation problems in object-oriented programming.
  • The Builder design pattern provides a way to separate the construction of a complex object from its representation.
  • The Builder pattern constructs a complex object by using simple objects and step by step approach.
  •  The pattern provides one of the best ways to create a complex object.
  •  It is one of the Gang of Four design patterns that describe how to solve recurring design problems in object-oriented software.
  • This pattern is useful to build different immutable objects using same object building process.

The builder pattern is a design pattern that allows for the step-by-step creation of complex objects using the correct sequence of actions. The construction is controlled by a director object that only needs to know the type of object it is to create.

builder design pattern

So the important components of Builder Design Pattern are as below:

  • Product — The Class which defines the complex object we are trying to build step by step using simple objects.
  • Builder — The abstract class/interface which defines all the steps required to perform to produce the complex Product object. Generally, each step is declared here (abstract) since the implementation comes under the concrete builder class. 
  • ConcreteBuilder — The Builder class which provides the actual code to build the Product object. We can have number of different ConcreteBuilder classes each one giving a different flavor or way of producing the Product object.
  • Director — The class under which supervision builder performs the ordered steps to build the Product object. The Director normally receives the builder to perform the steps in correct order to build the Product object.

The Builder design pattern solves problems like:

  • How can a class (the same construction process) create different representations of a complex object?
  • How can a class that includes creating a complex object be simplified?

Let's implements a Car Manufacturing Example using Builder Design Pattern.

Car Manufacturing Example Using Builder Design Pattern

Step 1: Create Car class which is Product in our example:

Java
 




xxxxxxxxxx
1
69


 
1
package org.trishinfotech.builder;
2

          
3
public class Car {
4

          
5
    private String chassis;
6
    private String body;
7
    private String paint;
8
    private String interior;
9

          
10
    public Car() {
11
        super();
12
    }
13

          
14
    public Car(String chassis, String body, String paint, String interior) {
15
        this();
16
        this.chassis = chassis;
17
        this.body = body;
18
        this.paint = paint;
19
        this.interior = interior;
20
    }
21

          
22
    public String getChassis() {
23
        return chassis;
24
    }
25

          
26
    public void setChassis(String chassis) {
27
        this.chassis = chassis;
28
    }
29

          
30
    public String getBody() {
31
        return body;
32
    }
33

          
34
    public void setBody(String body) {
35
        this.body = body;
36
    }
37

          
38
    public String getPaint() {
39
        return paint;
40
    }
41

          
42
    public void setPaint(String paint) {
43
        this.paint = paint;
44
    }
45

          
46
    public String getInterior() {
47
        return interior;
48
    }
49

          
50
    public void setInterior(String interior) {
51
        this.interior = interior;
52
    }
53

          
54
    public boolean doQualityCheck() {
55
        return (chassis != null && !chassis.trim().isEmpty()) && (body != null && !body.trim().isEmpty())
56
                && (paint != null && !paint.trim().isEmpty()) && (interior != null && !interior.trim().isEmpty());
57
    }
58

          
59
    @Override
60
    public String toString() {
61
        // StringBuilder class also uses Builder Design Pattern with implementation of java.lang.Appendable interface
62
        StringBuilder builder = new StringBuilder();
63
        builder.append("Car [chassis=").append(chassis).append(", body=").append(body).append(", paint=").append(paint)
64
                .append(", interior=").append(interior).append("]");
65
        return builder.toString();
66
    }
67
    
68
}
68
}



Please note here that I have added a validation method doQualityCheck in the class. I believe Builder should not produce any incomplete or invalid Product object. So this method will help us in validating the car manufacturing.

Step 2: Create the CarBuilder abstract class/interface to define all of the required steps to build the Car.

Java
 




xxxxxxxxxx
1
20


 
1
package org.trishinfotech.builder;
2

          
3
public interface CarBuilder {
4

          
5
    // Step 1
6
    public CarBuilder fixChassis();
7

          
8
    // Step 2
9
    public CarBuilder fixBody();
10

          
11
    // Step 3
12
    public CarBuilder paint();
13

          
14
    // Step 4
15
    public CarBuilder fixInterior();
16

          
17
    // delivery of car
18
    public Car build();
19
}



Please notice that I made the return type CarBuilder as return type of all steps created here. This will help us in steps calling in a chained way. Here, one very important method build which is to get the result or create final object of Car.  This method will actually checks the validity of the car and delivers (returns) it only if its manufacturing is complete (valid).

Step 3: Now it's time to write ConcreteBuilder. As I mentioned that we can have different flavors of ConcreteBuilder and each one performs its manufacturing in its own way to provide different representations on the Complex Car object.

So, here we have code of ClassicCarBuilder which manufacture old car model.

Java
 




x


 
1
package org.trishinfotech.builder;
2
3
public class ClassicCarBuilder implements CarBuilder {
4
5
    private String chassis;
6
    private String body;
7
    private String paint;
8
    private String interior;
9
10
    public ClassicCarBuilder() {
11
        super();
12
    }
13
14
    @Override
15
    public CarBuilder fixChassis() {
16
        System.out.println("Assembling chassis of the classical model");
17
        this.chassis = "Classic Chassis";
18
        return this;
19
    }
20
21
    @Override
22
    public CarBuilder fixBody() {
23
        System.out.println("Assembling body of the classical model");
24
        this.body = "Classic Body";
25
        return this;
26
    }
27
28
    @Override
29
    public CarBuilder paint() {
30
        System.out.println("Painting body of the classical model");
31
        this.paint = "Classic White Paint";
32
        return this;
33
    }
34
35
    @Override
36
    public CarBuilder fixInterior() {
37
        System.out.println("Setting up interior of the classical model");
38
        this.interior = "Classic interior";
39
        return this;
40
    }
41
42
    @Override
43
    public Car build() {
44
        Car car = new Car(chassis, body, paint, interior);
45
        if (car.doQualityCheck()) {
46
            return car;
47
        } else {
48
            System.out.println("Car assembly is incomplete. Can't deliver!");
49
        }
50
        return null;
51
    }
52
53
}



Now another builder ModernCarBuilder to build a latest car model.

Java
 




x


 
1
package org.trishinfotech.builder;
2

          
3
public class ModernCarBuilder implements CarBuilder {
4

          
5
    private String chassis;
6
    private String body;
7
    private String paint;
8
    private String interior;
9

          
10
    public ModernCarBuilder() {
11
        super();
12
    }
13

          
14
    @Override
15
    public CarBuilder fixChassis() {
16
        System.out.println("Assembling chassis of the modern model");
17
        this.chassis = "Modern Chassis";
18
        return this;
19
    }
20

          
21
    @Override
22
    public CarBuilder fixBody() {
23
        System.out.println("Assembling body of the modern model");
24
        this.body = "Modern Body";
25
        return this;
26
    }
27

          
28
    @Override
29
    public CarBuilder paint() {
30
        System.out.println("Painting body of the modern model");
31
        this.paint = "Modern Black Paint";
32
        return this;
33
    }
34

          
35
    @Override
36
    public CarBuilder fixInterior() {
37
        System.out.println("Setting up interior of the modern model");
38
        this.interior = "Modern interior";
39
        return this;
40
    }
41

          
42
    @Override
43
    public Car build() {
44
        Car car = new Car(chassis, body, paint, interior);
45
        if (car.doQualityCheck()) {
46
            return car;
47
        } else {
48
            System.out.println("Car assembly is incomplete. Can't deliver!");
49
        }
50
        return null;
51
    }
52

          
53
}



And another SportsCarBuilder to build a sports car.

Java
 




xxxxxxxxxx
1
54


 
1
package org.trishinfotech.builder;
2

          
3
public class SportsCarBuilder implements CarBuilder {
4

          
5
    private String chassis;
6
    private String body;
7
    private String paint;
8
    private String interior;
9

          
10
    public SportsCarBuilder() {
11
        super();
12
    }
13

          
14
    @Override
15
    public CarBuilder fixChassis() {
16
        System.out.println("Assembling chassis of the sports model");
17
        this.chassis = "Sporty Chassis";
18
        return this;
19
    }
20

          
21
    @Override
22
    public CarBuilder fixBody() {
23
        System.out.println("Assembling body of the sports model");
24
        this.body = "Sporty Body";
25
        return this;
26
    }
27

          
28
    @Override
29
    public CarBuilder paint() {
30
        System.out.println("Painting body of the sports model");
31
        this.paint = "Sporty Torch Red Paint";
32
        return this;
33
    }
34

          
35
    @Override
36
    public CarBuilder fixInterior() {
37
        System.out.println("Setting up interior of the sports model");
38
        this.interior = "Sporty interior";
39
        return this;
40
    }
41

          
42
    @Override
43
    public Car build() {
44
        Car car = new Car(chassis, body, paint, interior);
45
        if (car.doQualityCheck()) {
46
            return car;
47
        } else {
48
            System.out.println("Car assembly is incomplete. Can't deliver!");
49
        }
50
        return null;
51
    }
52

          
53
}



Step 4: Now we will write a Director class call AutomotiveEngineer under which supervision the builder will build the Car in step by step in correct order. 

Java
 




xxxxxxxxxx
1
20


 
1
package org.trishinfotech.builder;
2

          
3
public class AutomotiveEngineer {
4

          
5
    private CarBuilder builder;
6

          
7
    public AutomotiveEngineer(CarBuilder builder) {
8
        super();
9
        this.builder = builder;
10
        if (this.builder == null) {
11
            throw new IllegalArgumentException("Automotive Engineer can't work without Car Builder!");
12
        }
13
    }
14

          
15
    public Car manufactureCar() {
16
        return builder.fixChassis().fixBody().paint().fixInterior().build();
17
    }
18

          
19
}



We can see that the manufactureCar method is calling the car building steps in correct order.

Now, it's time to write a Main class to execute and test the output.

Java
 




xxxxxxxxxx
1
18


 
1
package org.trishinfotech.builder;
2

          
3
public class Main {
4

          
5
    public static void main(String[] args) {
6
        CarBuilder builder = new SportsCarBuilder();
7
        AutomotiveEngineer engineer = new AutomotiveEngineer(builder);
8
        Car car = engineer.manufactureCar();
9
        if (car != null) {
10
            System.out.println("Below car delievered: ");
11
            System.out.println("======================================================================");
12
            System.out.println(car);
13
            System.out.println("======================================================================");
14
        }
15
    }
16

          
17
}



Below is the output of the program:

Java
 




xxxxxxxxxx
1


 
1
Assembling chassis of the sports model
2
Assembling body of the sports model
3
Painting body of the sports model
4
Setting up interior of the sports model
5
Below car delievered: 
6
======================================================================
7
Car [chassis=Sporty Chassis, body=Sporty Body, paint=Sporty Torch Red Paint, interior=Sporty interior]
8
======================================================================



I hope we are good with the explanation and example to understand the Builder Pattern. Few of us also find this matching with Abstract Factory Pattern which I have covered in my another article. The main difference between Builder Pattern and Abstract Factory Pattern is that, Builder provides us more or better control over the object creation process.  In short Abstract Factory Pattern deals with "WHAT" and Builder Pattern deals with "HOW".

The Builder Design Pattern is a design pattern that allows for the step-by-step creation of complex objects using the correct sequence of actions. The construction is controlled by a director object that only needs to know the type of object it is to create.

Source Code can be found here: Real-Builder-Design-Pattern-Source-Code

I found builder pattern very useful and one of the most commonly used in the applications nowadays. I found Builder more useful while dealing with the immutable objects. We all know how much good immutable objects and the use of immutable objects is getting increased day by day, especially after release of Java 8.

I use Builder for writing my immutable complex classes and I like to present the idea here.

As an Example, We have an Employee class in which we have number of fields. 

Java
 




xxxxxxxxxx
1


 
1
public class Employee {
2

          
3
    private int empNo;
4
    private String name;
5
    private String depttName;
6
    private int salary;
7
    private int mgrEmpNo;
8
    private String projectName;
9
}



Suppose only 2 fields EmpNo and EmpName are mandatory, and the rest all are optional. Since it's an immutable class, I have 2 choice while writing constructors.

  1. Write a constructor with the parameters for all the fields.
  2. Write multiple constructors for different combination of parameters to create different representations of Employee object.

I thought option 1 is not good since I don't like to have more than 3-4 parameters in a method. That's not look good and it even worst when many of parameters are null or zero.

Java
 




xxxxxxxxxx
1


 
1
Employee emp1 = new Employee (100, "Brijesh", null, 0, 0, "Builder Pattern");



Option 2 is also not very good since we end up creating too many constructors.

Java
 




xxxxxxxxxx
1
32


 
1
    public Employee(int empNo, String name) {
2
        super();
3
        if (empNo <= 0) {
4
            throw new IllegalArgumentException("Please provide valid employee number.");
5
        }
6
        if (name == null || name.trim().isEmpty()) {
7
            throw new IllegalArgumentException("Please provide employee name.");
8
        }
9
        this.empNo = empNo;
10
        this.name = name;
11
    }
12

          
13
    public Employee(int empNo, String name, String depttName) {
14
        this(empNo, name);
15
        this.depttName = depttName;
16
    }
17

          
18
    public Employee(int empNo, String name, String depttName, int salary) {
19
        this(empNo, name, depttName);
20
        this.salary = salary;
21
    }
22

          
23
    public Employee(int empNo, String name, String depttName, int salary, int mgrEmpNo) {
24
        this(empNo, name, depttName, salary);
25
        this.mgrEmpNo = mgrEmpNo;
26
    }
27

          
28
    public Employee(int empNo, String name, String depttName, int salary, int mgrEmpNo, String projectName) {
29
        this(empNo, name, depttName, salary, mgrEmpNo);
30
        this.projectName = projectName;
31
    }



So, here is the solution with the help of Builder Pattern:

Java
 




xxxxxxxxxx
1
122


 
1
package org.trishinfotech.builder.example;
2

          
3
public class Employee {
4

          
5
    private int empNo;
6
    private String name;
7
    private String depttName;
8
    private int salary;
9
    private int mgrEmpNo;
10
    private String projectName;
11

          
12
    public Employee(EmployeeBuilder employeeBuilder) {
13
        if (employeeBuilder == null) {
14
            throw new IllegalArgumentException("Please provide employee builder to build employee object.");
15
        }
16
        if (employeeBuilder.empNo <= 0) {
17
            throw new IllegalArgumentException("Please provide valid employee number.");
18
        }
19
        if (employeeBuilder.name == null || employeeBuilder.name.trim().isEmpty()) {
20
            throw new IllegalArgumentException("Please provide employee name.");
21
        }
22
        this.empNo = employeeBuilder.empNo;
23
        this.name = employeeBuilder.name;
24
        this.depttName = employeeBuilder.depttName;
25
        this.salary = employeeBuilder.salary;
26
        this.mgrEmpNo = employeeBuilder.mgrEmpNo;
27
        this.projectName = employeeBuilder.projectName;
28
    }
29

          
30
    public int getEmpNo() {
31
        return empNo;
32
    }
33

          
34
    public String getName() {
35
        return name;
36
    }
37

          
38
    public String getDepttName() {
39
        return depttName;
40
    }
41

          
42
    public int getSalary() {
43
        return salary;
44
    }
45

          
46
    public int getMgrEmpNo() {
47
        return mgrEmpNo;
48
    }
49

          
50
    public String getProjectName() {
51
        return projectName;
52
    }
53

          
54
    @Override
55
    public String toString() {
56
        // StringBuilder class also uses Builder Design Pattern with implementation of
57
        // java.lang.Appendable interface
58
        StringBuilder builder = new StringBuilder();
59
        builder.append("Employee [empNo=").append(empNo).append(", name=").append(name).append(", depttName=")
60
                .append(depttName).append(", salary=").append(salary).append(", mgrEmpNo=").append(mgrEmpNo)
61
                .append(", projectName=").append(projectName).append("]");
62
        return builder.toString();
63
    }
64

          
65
    public static class EmployeeBuilder {
66
        private int empNo;
67
        protected String name;
68
        protected String depttName;
69
        protected int salary;
70
        protected int mgrEmpNo;
71
        protected String projectName;
72

          
73
        public EmployeeBuilder() {
74
            super();
75
        }
76

          
77
        public EmployeeBuilder empNo(int empNo) {
78
            this.empNo = empNo;
79
            return this;
80
        }
81

          
82
        public EmployeeBuilder name(String name) {
83
            this.name = name;
84
            return this;
85
        }
86

          
87
        public EmployeeBuilder depttName(String depttName) {
88
            this.depttName = depttName;
89
            return this;
90
        }
91

          
92
        public EmployeeBuilder salary(int salary) {
93
            this.salary = salary;
94
            return this;
95
        }
96

          
97
        public EmployeeBuilder mgrEmpNo(int mgrEmpNo) {
98
            this.mgrEmpNo = mgrEmpNo;
99
            return this;
100
        }
101

          
102
        public EmployeeBuilder projectName(String projectName) {
103
            this.projectName = projectName;
104
            return this;
105
        }
106

          
107
        public Employee build() {
108
            Employee emp = null;
109
            if (validateEmployee()) {
110
                emp = new Employee(this);
111
            } else {
112
                System.out.println("Sorry! Employee objects can't be build without required details");
113
            }
114
            return emp;
115
        }
116

          
117
        private boolean validateEmployee() {
118
            return (empNo > 0 && name != null && !name.trim().isEmpty());
119
        }
120
    }
121
}



I wrote EmployeeBuilder as a public static nested class. You can write as normal public class in a separate Java file. There is not much difference in both.

Now a EmployeeMain program to execute and create an Employee object:

Java
 




xxxxxxxxxx
1
11


 
1
package org.trishinfotech.builder.example;
2

          
3
public class EmployeeMain {
4

          
5
    public static void main(String[] args) {
6
        Employee emp1 = new Employee.EmployeeBuilder().empNo(100).name("Brijesh").projectName("Builder Pattern")
7
                .build();
8
        System.out.println(emp1);
9
    }
10
}



I hope you like the idea. We can use this even in creating more complex objects. I did not wrote Director here, since all steps (collecting values for fields) are not compulsory and can be done in any order. Just to make sure, I am creating an Employee object only after getting all the mandatory fields, I wrote a validation method.

Restaurant Order Placement Example With Builder Pattern

I am sharing code for a Restaurant Order Placement where Order is immutable object and requires Order Service Type (Take Away/Eat Here), all the Food Items we want, and the Customer Name(optional) at the time of placing the order. Food Items can be as many as we want. So, here is the code for the example.

Code for OrderService enum:

Java
 




xxxxxxxxxx
1
24


 
1
package org.trishinfotech.builder;
2

          
3
public enum OrderService {
4

          
5
    TAKE_AWAY("Take Away", 2.0d), EAT_HERE("Eat Here", 5.5d);
6

          
7
    private String name;
8
    private double tax;
9

          
10
    OrderService(String name, double tax) {
11
        this.name = name;
12
        this.tax = tax;
13
    }
14

          
15
    public String getName() {
16
        return name;
17
    }
18

          
19
    public double getTax() {
20
        return tax;
21
    }
22

          
23
}



Code for FoodItem interface:

Java
 




xxxxxxxxxx
1
15


 
1
package org.trishinfotech.builder.meal;
2

          
3
import org.trishinfotech.builder.packing.Packing;
4

          
5
public interface FoodItem {
6

          
7
    public String name();
8

          
9
    public int calories();
10

          
11
    public Packing packing();
12

          
13
    public double price();
14
}



Code for Meal class. The Meal class offers predefined food-items with discount on item-price (not on packing-price).

Java
 




xxxxxxxxxx
1
60


 
1
package org.trishinfotech.builder.meal;
2

          
3
import java.util.ArrayList;
4
import java.util.List;
5
import java.util.Objects;
6
import java.util.stream.Collectors;
7

          
8
import org.trishinfotech.builder.packing.MultiPack;
9
import org.trishinfotech.builder.packing.Packing;
10

          
11
public class Meal implements FoodItem {
12

          
13
    private List<FoodItem> foodItems = new ArrayList<FoodItem>();
14
    private String mealName;
15
    private double discount;
16

          
17
    public Meal(String mealName, List<FoodItem> foodItems, double discount) {
18
        super();
19
        if (Objects.isNull(foodItems) || foodItems.stream().filter(Objects::nonNull).collect(Collectors.toList()).isEmpty()) {
20
            throw new IllegalArgumentException(
21
                    "Meal can't be order without any food item");
22
        }
23
        this.mealName = mealName;
24
        this.foodItems = new ArrayList<FoodItem>(foodItems);
25
        this.discount = discount;
26
    }
27

          
28
    public List<FoodItem> getFoodItems() {
29
        return foodItems;
30
    }
31

          
32
    @Override
33
    public String name() {
34
        return mealName;
35
    }
36

          
37
    @Override
38
    public int calories() {
39
        int totalCalories = foodItems.stream().mapToInt(foodItem -> foodItem.calories()).sum();
40
        return totalCalories;
41
    }
42

          
43
    @Override
44
    public Packing packing() {
45
        double packingPrice = foodItems.stream().map(foodItem -> foodItem.packing())
46
                .mapToDouble(packing -> packing.packingPrice()).sum();
47
        return new MultiPack(packingPrice);
48
    }
49

          
50
    @Override
51
    public double price() {
52
        double totalPrice = foodItems.stream().mapToDouble(foodItem -> foodItem.price()).sum();
53
        return totalPrice;
54
    }
55

          
56
    public double discount() {
57
        return discount;
58
    }
59
}


Food:

Code for Burger class:

Java
 




xxxxxxxxxx
1
15


 
1
package org.trishinfotech.builder.food.burger;
2

          
3
import org.trishinfotech.builder.meal.FoodItem;
4
import org.trishinfotech.builder.packing.Packing;
5
import org.trishinfotech.builder.packing.Wrap;
6

          
7
public abstract class Burger implements FoodItem {
8

          
9
    @Override
10
    public Packing packing() {
11
        return new Wrap();
12
    }
13

          
14
}



Code for ChickenBurger class:

Java
 




xxxxxxxxxx
1
21


 
1
package org.trishinfotech.builder.food.burger;
2

          
3
public class ChickenBurger extends Burger {
4

          
5
    @Override
6
    public String name() {
7
        return "Chicken Burger";
8
    }
9

          
10
    @Override
11
    public int calories() {
12
        return 300;
13
    }
14

          
15
    @Override
16
    public double price() {
17
        return 4.5d;
18
    }
19

          
20
}



Code for VegBurger class:

Java
 




xxxxxxxxxx
1
21


 
1
package org.trishinfotech.builder.food.burger;
2

          
3
public class VegBurger extends Burger {
4

          
5
    @Override
6
    public String name() {
7
        return "Veg Burger";
8
    }
9

          
10
    @Override
11
    public int calories() {
12
        return 180;
13
    }
14

          
15
    @Override
16
    public double price() {
17
        return 2.7d;
18
    }
19

          
20
}



Code for Nuggets class:

Java
 




xxxxxxxxxx
1
15


 
1
package org.trishinfotech.builder.food.nuggets;
2

          
3
import org.trishinfotech.builder.meal.FoodItem;
4
import org.trishinfotech.builder.packing.Container;
5
import org.trishinfotech.builder.packing.Packing;
6

          
7
public abstract class Nuggets implements FoodItem {
8

          
9
    @Override
10
    public Packing packing() {
11
        return new Container();
12
    }
13

          
14
}



Code for CheeseNuggets class:

Java
 




xxxxxxxxxx
1
21


 
1
package org.trishinfotech.builder.food.nuggets;
2

          
3
public class CheeseNuggets extends Nuggets {
4

          
5
    @Override
6
    public String name() {
7
        return "Cheese Nuggets";
8
    }
9

          
10
    @Override
11
    public int calories() {
12
        return 330;
13
    }
14

          
15
    @Override
16
    public double price() {
17
        return 3.8d;
18
    }
19

          
20
}



Code for ChickenNuggets class:

Java
 




xxxxxxxxxx
1
21


 
1
package org.trishinfotech.builder.food.nuggets;
2

          
3
public class ChickenNuggets extends Nuggets {
4

          
5
    @Override
6
    public String name() {
7
        return "Chicken Nuggets";
8
    }
9

          
10
    @Override
11
    public int calories() {
12
        return 450;
13
    }
14

          
15
    @Override
16
    public double price() {
17
        return 5.0d;
18
    }
19

          
20
}


Beverages:

Beverages comes in a size. So, here is the code for BeverageSize enum:

Java
 




xxxxxxxxxx
1
23


 
1
package org.trishinfotech.builder.beverages;
2

          
3
public enum BeverageSize {
4
    XS("Extra Small", 110), S("Small", 150), M("Medium", 210), L("Large", 290);
5

          
6
    private String name;
7
    private int calories;
8

          
9
    BeverageSize(String name, int calories) {
10
        this.name = name;
11
        this.calories = calories;
12
    }
13

          
14
    public String getName() {
15
        return name;
16
    }
17

          
18
    public int getCalories() {
19
        return calories;
20
    }
21

          
22
}



Code for Drink class:

Java
 




xxxxxxxxxx
1
25


 
1
package org.trishinfotech.builder.beverages;
2

          
3
import org.trishinfotech.builder.meal.FoodItem;
4

          
5
public abstract class Drink implements FoodItem {
6
    
7
    protected BeverageSize size;
8

          
9
    public Drink(BeverageSize size) {
10
        super();
11
        this.size = size;
12
        if (this.size == null) {
13
            this.size = BeverageSize.M;
14
        }
15
    }
16

          
17
    public BeverageSize getSize() {
18
        return size;
19
    }
20
    
21
    public String drinkDetails() {
22
        return " (" + size + ")";
23
    }
24
}



Code for ColdDrink class:

Java
 




xxxxxxxxxx
1
18


 
1
package org.trishinfotech.builder.beverages.cold;
2

          
3
import org.trishinfotech.builder.beverages.BeverageSize;
4
import org.trishinfotech.builder.beverages.Drink;
5
import org.trishinfotech.builder.packing.Bottle;
6
import org.trishinfotech.builder.packing.Packing;
7

          
8
public abstract class ColdDrink extends Drink {
9

          
10
    public ColdDrink(BeverageSize size) {
11
        super(size);
12
    }
13

          
14
    @Override public Packing packing() {
15
        return new Bottle();
16
    }
17
}
18

          



Code for CocaCola class:

Java
 




xxxxxxxxxx
1
55


 
1
package org.trishinfotech.builder.beverages.cold;
2

          
3
import org.trishinfotech.builder.beverages.BeverageSize;
4

          
5
public class CocaCola extends ColdDrink {
6

          
7
    public CocaCola(BeverageSize size) {
8
        super(size);
9
    }
10

          
11
    @Override
12
    public String name() {
13
        return "Coca-Cola" + drinkDetails();
14
    }
15

          
16
    @Override
17
    public int calories() {
18
        if (size != null) {
19
            switch (size) {
20
            case XS:
21
                return 110;
22
            case S:
23
                return 150;
24
            case M:
25
                return 210;
26
            case L:
27
                return 290;
28
            default:
29
                break;
30
            }
31
        }
32
        return 0;
33
    }
34

          
35
    @Override
36
    public double price() {
37
        if (size != null) {
38
            switch (size) {
39
            case XS:
40
                return 0.80d;
41
            case S:
42
                return 1.0d;
43
            case M:
44
                return 1.5d;
45
            case L:
46
                return 2.0d;
47
            default:
48
                break;
49
            }
50
        }
51
        return 0.0d;
52
    }
53

          
54
}



Code for Pepsi class:

Java
 




xxxxxxxxxx
1
48


 
1
package org.trishinfotech.builder.beverages.cold;
2

          
3
import org.trishinfotech.builder.beverages.BeverageSize;
4

          
5
public class Pepsi extends ColdDrink {
6

          
7
    public Pepsi(BeverageSize size) {
8
        super(size);
9
    }
10
    
11
    @Override public String name() {
12
        return "Pepsi" + drinkDetails();
13
    }
14

          
15
    @Override public int calories() {
16
        if (size != null) {
17
            switch (size) {
18
                case S:
19
                    return 160;
20
                case M:
21
                    return 220;
22
                case L:
23
                    return 300;
24
                default:
25
                    break;
26
            }
27
        }
28
        return 0;
29
    }
30
    
31
    @Override public double price() {
32
        if (size != null) {
33
            switch (size) {
34
                case S:
35
                    return 1.2d;
36
                case M:
37
                    return 2.2d;
38
                case L:
39
                    return 2.7d;
40
                default:
41
                    break;
42
            }
43
        }
44
        return 0.0d;
45
    }
46

          
47
}



Code for HotDrink class:

Java
 




xxxxxxxxxx
1
18


 
1
package org.trishinfotech.builder.beverages.hot;
2

          
3
import org.trishinfotech.builder.beverages.BeverageSize;
4
import org.trishinfotech.builder.beverages.Drink;
5
import org.trishinfotech.builder.packing.Packing;
6
import org.trishinfotech.builder.packing.SipperMug;
7

          
8
public abstract class HotDrink extends Drink {
9

          
10
    public HotDrink(BeverageSize size) {
11
        super(size);
12
    }
13

          
14
    @Override public Packing packing() {
15
        return new SipperMug();
16
    }
17
}



Code for Cuppuccinno class

Java
 




xxxxxxxxxx
1
48


 
1
package org.trishinfotech.builder.beverages.hot;
2

          
3
import org.trishinfotech.builder.beverages.BeverageSize;
4

          
5
public class Cappuccino extends HotDrink {
6

          
7
    public Cappuccino(BeverageSize size) {
8
        super(size);
9
    }
10
    
11
    @Override public String name() {
12
        return "Cappuccino" + drinkDetails();
13
    }
14

          
15
    @Override public int calories() {
16
        if (size != null) {
17
            switch (size) {
18
                case S:
19
                    return 120;
20
                case M:
21
                    return 160;
22
                case L:
23
                    return 210;
24
                default:
25
                break;
26
            }
27
        }
28
        return 0;
29
    }
30
    
31
    @Override public double price() {
32
        if (size != null) {
33
            switch (size) {
34
                case S:
35
                    return 1.0d;
36
                case M:
37
                    return 1.4d;
38
                case L:
39
                    return 1.8d;
40
                default:
41
                break;
42
            }
43
        }
44
        return 0.0d;
45
    }
46

          
47
}
48

          



Code for HotChocolate class:

Java
 




xxxxxxxxxx
1
48


 
1
package org.trishinfotech.builder.beverages.hot;
2

          
3
import org.trishinfotech.builder.beverages.BeverageSize;
4

          
5
public class HotChocolate extends HotDrink {
6

          
7
    public HotChocolate(BeverageSize size) {
8
        super(size);
9
    }
10
    
11
    @Override public String name() {
12
        return "Hot Chocolate" + drinkDetails();
13
    }
14

          
15
    @Override public int calories() {
16
        if (size != null) {
17
            switch (size) {
18
                case S:
19
                    return 370;
20
                case M:
21
                    return 450;
22
                case L:
23
                    return 560;
24
                default:
25
                    break;
26
            }
27
        }
28
        return 0;
29
    }
30
    
31
    @Override public double price() {
32
        if (size != null) {
33
            switch (size) {
34
                case S:
35
                    return 1.6d;
36
                case M:
37
                    return 2.3d;
38
                case L:
39
                    return 3.0d;
40
                default:
41
                    break;
42
            }
43
        }
44
        return 0.0d;
45
    }
46

          
47
}


Packing:

Code for Packing interface:

Java
 




xxxxxxxxxx
1


 
1
package org.trishinfotech.builder.packing;
2

          
3
public interface Packing {
4
    
5
    public String pack();
6

          
7
    public double packingPrice();
8
}



Code for Bottle class:

Java
 




xxxxxxxxxx
1
16


 
1
package org.trishinfotech.builder.packing;
2

          
3
public class Bottle implements Packing {
4

          
5
    @Override
6
    public String pack() {
7
        return "Bottle";
8
    }
9

          
10
    @Override
11
    public double packingPrice() {
12
        return 0.75d;
13
    }
14

          
15
}



Code for Container class:

Java
 




xxxxxxxxxx
1
16


 
1
package org.trishinfotech.builder.packing;
2

          
3
public class Container implements Packing {
4

          
5
    @Override
6
    public String pack() {
7
        return "Container";
8
    }
9

          
10
    @Override
11
    public double packingPrice() {
12
        return 1.25d;
13
    }
14

          
15
}



Code for MultiPack class. MutiPack packing to support Meal packing where we use different packing for different food items.

Java
 




xxxxxxxxxx
1
23


 
1
package org.trishinfotech.builder.packing;
2

          
3
public class MultiPack implements Packing {
4

          
5
    private double packingPrice;
6
    
7
    public MultiPack(double packingPrice) {
8
        super();
9
        this.packingPrice = packingPrice;
10
    }
11

          
12
    @Override
13
    public String pack() {
14
        return "Multi-Pack";
15
    }
16

          
17
    @Override
18
    public double packingPrice() {
19
        return packingPrice;
20
    }
21

          
22
}



Code for SipperMug class:

Java
 




x


 
1
package org.trishinfotech.builder.packing;
2

          
3
public class SipperMug implements Packing {
4

          
5
    @Override
6
    public String pack() {
7
        return "Sipper Mug";
8
    }
9

          
10
    @Override
11
    public double packingPrice() {
12
        return 1.6d;
13
    }
14

          
15
}



Code for Wrap class:

Java
 




xxxxxxxxxx
1
16


 
1
package org.trishinfotech.builder.packing;
2

          
3
public class Wrap implements Packing {
4

          
5
    @Override
6
    public String pack() {
7
        return "Wrap";
8
    }
9

          
10
    @Override
11
    public double packingPrice() {
12
        return 0.40d;
13
    }
14

          
15
}



Code for utility BillPrinter class which I wrote to print an itemized bill.

Java
 




x


 
1
package org.trishinfotech.builder.util;
2

          
3
import java.time.LocalDateTime;
4
import java.time.format.DateTimeFormatter;
5
import java.util.concurrent.atomic.DoubleAdder;
6

          
7
import org.trishinfotech.builder.Order;
8
import org.trishinfotech.builder.OrderService;
9
import org.trishinfotech.builder.meal.Meal;
10
import org.trishinfotech.builder.packing.Packing;
11

          
12
public class BillPrinter {
13

          
14
    static DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
15
    
16
    public static void printItemisedBill(Order order) {
17
        OrderService service = order.getService();
18
        System.out.printf("%60s\n", "Food Court");
19
        System.out.println("=================================================================================================================");
20
        System.out.printf("Service: %10s (%2.2f Tax)                                                         Customer Name: %-20s\n", service.getName(), service.getTax(), order.getCustomerName());
21
        System.out.println("-----------------------------------------------------------------------------------------------------------------");
22
        System.out.printf("%25s | %10s | %10s | %10s | %15s | %10s | %10s\n", "Food Item", "Calories", "Packing", "Price", "Packing Price", "Discount %", "Total Price");
23
        System.out.println("-----------------------------------------------------------------------------------------------------------------");
24
        DoubleAdder itemTotalPrice = new DoubleAdder();
25
        order.getFoodItems().stream().forEach(item -> {
26
            String name = item.name();
27
            int calories = item.calories();
28
            Packing packing = item.packing();
29
            double price = item.price();
30
            double packingPrice = packing.packingPrice();
31
            double discount = item instanceof Meal? ((Meal)item).discount() : 0.0d;
32
            double totalItemPrice = calculateTotalItemPrice(price, packingPrice, discount);
33
            System.out.printf("%25s | %10d | %10s | %10.2f | %15.2f | %10.2f | %10.2f\n", name, calories, packing.pack(), price, packing.packingPrice(), discount, totalItemPrice);
34
            itemTotalPrice.add(totalItemPrice);
35
        });
36
        System.out.println("=================================================================================================================");
37
        double billTotal = itemTotalPrice.doubleValue();
38
        billTotal = applyTaxes(billTotal, service);
39
        System.out.printf("Date: %-30s %66s %.2f\n", dtf.format(LocalDateTime.now()), "Total Bill (incl. taxes):", billTotal);
40
        System.out.println("Enjoy your meal!\n\n\n\n");
41
    }
42

          
43
    private static double applyTaxes(double billTotal, OrderService service) {
44
        return billTotal + (billTotal * service.getTax())/100;
45
    }
46

          
47
    private static double calculateTotalItemPrice(double price, double packingPrice, double discount) {
48
        if (discount > 0.0d) {
49
            price = price - (price * discount)/100;
50
        }
51
        return price + packingPrice;
52
    }
53
}



Now, since almost everything is ready. It's time to write our immutable Order class:

Java
 




xxxxxxxxxx
1
48


 
1
package org.trishinfotech.builder;
2

          
3
import java.util.ArrayList;
4
import java.util.List;
5
import java.util.Objects;
6
import java.util.stream.Collectors;
7

          
8
import org.trishinfotech.builder.meal.FoodItem;
9

          
10
public class Order {
11

          
12
    private List<FoodItem> foodItems = new ArrayList<FoodItem>();
13

          
14
    private String customerName;
15
    private OrderService service;
16

          
17
    public Order(OrderService service, List<FoodItem> foodItems, String customerName) {
18
        super();
19
        if (Objects.isNull(service)) {
20
            throw new IllegalArgumentException(
21
                    "Meal can't be order without selecting service 'Take Away' or 'Eat Here'");
22
        }
23
        if (Objects.isNull(foodItems) || foodItems.stream().filter(Objects::nonNull).collect(Collectors.toList()).isEmpty()) {
24
            throw new IllegalArgumentException(
25
                    "Meal can't be order without any food item");
26
        }
27
        this.service = service;
28
        this.foodItems = new ArrayList<FoodItem>(foodItems);
29
        this.customerName = customerName;
30
        if (this.customerName == null) {
31
            this.customerName = "NO NAME";
32
        }
33
    }
34

          
35
    public List<FoodItem> getFoodItems() {
36
        return foodItems;
37
    }
38

          
39
    public String getCustomerName() {
40
        return customerName;
41
    }
42

          
43
    public OrderService getService() {
44
        return service;
45
    }
46

          
47
}



And now here is the code for OrderBuilder, which will build the Order object.

Java
 




xxxxxxxxxx
1
95


 
1
package org.trishinfotech.builder;
2

          
3
import java.util.ArrayList;
4
import java.util.List;
5

          
6
import org.trishinfotech.builder.beverages.BeverageSize;
7
import org.trishinfotech.builder.beverages.cold.CocaCola;
8
import org.trishinfotech.builder.beverages.cold.Pepsi;
9
import org.trishinfotech.builder.food.burger.ChickenBurger;
10
import org.trishinfotech.builder.food.burger.VegBurger;
11
import org.trishinfotech.builder.food.nuggets.CheeseNuggets;
12
import org.trishinfotech.builder.food.nuggets.ChickenNuggets;
13
import org.trishinfotech.builder.meal.FoodItem;
14
import org.trishinfotech.builder.meal.Meal;
15

          
16
public class OrderBuilder {
17

          
18
    protected static final double HAPPY_MENU_DISCOUNT = 5.0d;
19

          
20
    private String customerName;
21

          
22
    private OrderService service = OrderService.TAKE_AWAY;
23

          
24
    private List<FoodItem> items = new ArrayList<FoodItem>();
25

          
26
    public OrderBuilder() {
27
        super();
28
    }
29

          
30
    // Setters for each of the fields we have in the target object. In this example its Order.
31
    // We are having return type as Builder itself (i.e. OrderBuilder) to make chained calling of setters possible.
32
    public OrderBuilder name(String customerName) {
33
        this.customerName = customerName;
34
        return this;
35
    }
36

          
37
    public OrderBuilder service(OrderService service) {
38
        if (service != null) {
39
            this.service = service;
40
        }
41
        return this;
42
    }
43

          
44
    public OrderBuilder item(FoodItem item) {
45
        items.add(item);
46
        return this;
47
    }
48

          
49
    // Happy Menus
50
    public OrderBuilder vegNuggetsHappyMeal() {
51
        List<FoodItem> foodItems = new ArrayList<FoodItem>();
52
        foodItems.add(new CheeseNuggets());
53
        foodItems.add(new Pepsi(BeverageSize.S));
54
        Meal meal = new Meal("Veg Nuggets Happy Meal", foodItems, HAPPY_MENU_DISCOUNT);
55
        return item(meal);
56
    }
57

          
58
    public OrderBuilder chickenNuggetsHappyMeal() {
59
        List<FoodItem> foodItems = new ArrayList<FoodItem>();
60
        foodItems.add(new ChickenNuggets());
61
        foodItems.add(new CocaCola(BeverageSize.S));
62
        Meal meal = new Meal("Chicken Nuggets Happy Meal", foodItems, HAPPY_MENU_DISCOUNT);
63
        return item(meal);
64
    }
65

          
66
    public OrderBuilder vegBurgerHappyMeal() {
67
        List<FoodItem> foodItems = new ArrayList<FoodItem>();
68
        foodItems.add(new VegBurger());
69
        foodItems.add(new Pepsi(BeverageSize.S));
70
        Meal meal = new Meal("Veg Burger Happy Meal", foodItems, HAPPY_MENU_DISCOUNT);
71
        return item(meal);
72
    }
73

          
74
    public OrderBuilder chickenBurgerHappyMeal() {
75
        List<FoodItem> foodItems = new ArrayList<FoodItem>();
76
        foodItems.add(new ChickenBurger());
77
        foodItems.add(new CocaCola(BeverageSize.S));
78
        Meal meal = new Meal("Chicken Burger Happy Meal", foodItems, HAPPY_MENU_DISCOUNT);
79
        return item(meal);
80
    }
81

          
82
    public Order build() {
83
        Order order = new Order(service, items, customerName);
84
        if (!validateOrder()) {
85
            System.out.println("Sorry! Order can't be placed without service type (Take Away/Eat Here) and any food item.");
86
            return null;
87
        }
88
        return order;
89
    }
90

          
91
    private boolean validateOrder() {
92
        return (service != null) && !items.isEmpty();
93
    }
94
}



Done! Now it's time to write a Main program to execute and test the output:

Java
 




xxxxxxxxxx
1
30


 
1
package org.trishinfotech.builder;
2

          
3
import org.trishinfotech.builder.beverages.BeverageSize;
4
import org.trishinfotech.builder.beverages.cold.CocaCola;
5
import org.trishinfotech.builder.beverages.cold.Pepsi;
6
import org.trishinfotech.builder.beverages.hot.HotChocolate;
7
import org.trishinfotech.builder.food.burger.ChickenBurger;
8
import org.trishinfotech.builder.food.nuggets.CheeseNuggets;
9
import org.trishinfotech.builder.food.nuggets.ChickenNuggets;
10
import org.trishinfotech.builder.util.BillPrinter;
11

          
12
public class Main {
13

          
14
    public static void main(String[] args) {
15
        OrderBuilder builder1 = new OrderBuilder();
16
        // you can see the use of chained calls of setters here. No statement terminator
17
        // till we set all the values of the object
18
        Order meal1 = builder1.name("Brijesh").service(OrderService.TAKE_AWAY).item(new ChickenBurger())
19
                .item(new Pepsi(BeverageSize.M)).vegNuggetsHappyMeal().build();
20
        BillPrinter.printItemisedBill(meal1);
21

          
22
        OrderBuilder builder2 = new OrderBuilder();
23
        Order meal2 = builder2.name("Micheal").service(OrderService.EAT_HERE).item(new ChickenNuggets())
24
                .item(new CheeseNuggets()).item(new CocaCola(BeverageSize.L)).chickenBurgerHappyMeal()
25
                .item(new HotChocolate(BeverageSize.M)).vegBurgerHappyMeal().build();
26
        BillPrinter.printItemisedBill(meal2);
27
    }
28

          
29
}


 

And here's the output of the program:

Java
 




x


 
1
                                                  Food Court
2
=================================================================================================================
3
Service:  Take Away (2.00 Tax)                                                         Customer Name: Brijesh             
4
-----------------------------------------------------------------------------------------------------------------
5
                Food Item |   Calories |    Packing |      Price |   Packing Price | Discount % | Total Price
6
-----------------------------------------------------------------------------------------------------------------
7
           Chicken Burger |        300 |       Wrap |       4.50 |            0.40 |       0.00 |       4.90
8
                Pepsi (M) |        220 |     Bottle |       2.20 |            0.75 |       0.00 |       2.95
9
   Veg Nuggets Happy Meal |        490 | Multi-Pack |       5.00 |            2.00 |       5.00 |       6.75
10
=================================================================================================================
11
Date: 2020/10/09 20:02:38                                                     Total Bill (incl. taxes): 14.89
12
Enjoy your meal!
13
14
15
16
17
                                                  Food Court
18
=================================================================================================================
19
Service:   Eat Here (5.50 Tax)                                                         Customer Name: Micheal             
20
-----------------------------------------------------------------------------------------------------------------
21
                Food Item |   Calories |    Packing |      Price |   Packing Price | Discount % | Total Price
22
-----------------------------------------------------------------------------------------------------------------
23
          Chicken Nuggets |        450 |  Container |       5.00 |            1.25 |       0.00 |       6.25
24
           Cheese Nuggets |        330 |  Container |       3.80 |            1.25 |       0.00 |       5.05
25
            Coca-Cola (L) |        290 |     Bottle |       2.00 |            0.75 |       0.00 |       2.75
26
Chicken Burger Happy Meal |        450 | Multi-Pack |       5.50 |            1.15 |       5.00 |       6.38
27
        Hot Chocolate (M) |        450 | Sipper Mug |       2.30 |            1.60 |       0.00 |       3.90
28
    Veg Burger Happy Meal |        340 | Multi-Pack |       3.90 |            1.15 |       5.00 |       4.86
29
=================================================================================================================
30
Date: 2020/10/09 20:02:38                                                     Total Bill (incl. taxes): 30.78
31
Enjoy your meal!
32
33
34
35
36



Well, there you have it! I hope this tutorial helped to understand Builder pattern.

Source Code can be found here: Real-Builder-Design-Pattern-Source-Code

and Builder-Design-Pattern-Sample-Code

Liked the article? Please don't forget to press that like button. Happy coding!

Need more articles on Design Patterns? Please visit my profile to find more: Brijesh Saxena

Java (programming language) Design Object (computer science) Builder pattern Abstract factory pattern Build (game engine)

Opinions expressed by DZone contributors are their own.

Related

  • Object Relational Behavioral Design Patterns in Java
  • Distribution Design Patterns in Java - Data Transfer Object (DTO) And Remote Facade Design Patterns
  • Context Object Design Pattern in Java: Introduction and Key Points
  • Java: Object Pool Design Pattern

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!