The Builder Design Pattern in Java

In anticipation of the imminent start of the course "Architecture and Design Patterns", we are sharing with you the translation of the material.



We also invite everyone to an open demo lesson
"GRASP Templates" . In this lesson, we will analyze functional separation of functionality and look at 9 GRASP templates. Join us!






, Builder ( ). , .





Builder 

  • Builder - .





  • Builder .





  • Builder , .





  • .





  • (GoF), , - .





  • .





Builder β€” , . - (director), .





, Builder :





  • Product () - , , , .





  • Builder () - /, , -. , () (buildPart), (ConcreteBuilder).





  • ConcreteBuilder ( ) - -, -. ConcreteBuilder-, -.





  • Director () - , -. -.





Builder , :





  • ( ) ?





  • , ?





, Builder.





Builder

1: Car (), :





package org.trishinfotech.builder;

public class Car {

    private String chassis;
    private String body;
    private String paint;
    private String interior;
    
    public Car() {

        super();
    }

    public Car(String chassis, String body, String paint, String interior) {
        this();
        this.chassis = chassis;
        this.body = body;
        this.paint = paint;
        this.interior = interior;
    }

    public String getChassis() {
        return chassis;
    }

		public void setChassis(String chassis) {
        this.chassis = chassis;

    }

    public String getBody() {
        return body;
    }

    public void setBody(String body) {
        this.body = body;
    }

    public String getPaint() {
        return paint;
    }

    public void setPaint(String paint) {
        this.paint = paint;
    }
		public String getInterior() {
        return interior;
    }

    public void setInterior(String interior) {
        this.interior = interior;
    }

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

    @Override
    public String toString() {
        // StringBuilder class also uses Builder Design Pattern with implementation of java.lang.Appendable interface
        StringBuilder builder = new StringBuilder();
        builder.append("Car [chassis=").append(chassis).append(", body=").append(body).append(", paint=").append(paint)
        return builder.toString();
    }

}
      
      



, doQualityCheck



. , Builder Product-. , .





2: / CarBuilder



, .





package org.trishinfotech.builder;

public interface CarBuilder {

    //  1
    public CarBuilder fixChassis();

    //  2
    public CarBuilder fixBody();

    //  3
    public CarBuilder paint();

    //  4

    public CarBuilder fixInterior();

    //  

    public Car build();
}
      
      



, CarBuilder



, . . build



, , Car



. () , ( ).





3: ConcreteBuilder



. , ConcreteBuilder



, -, Car



.





, ClassicCarBuilder



, .





package org.trishinfotech.builder;

public class ClassicCarBuilder implements CarBuilder {

    private String chassis;
    private String body;
    private String paint;
    private String interior;

    public ClassicCarBuilder() {
        super();
    }

    @Override
    public CarBuilder fixChassis() {
        System.out.println("Assembling chassis of the classical model");
        this.chassis = "Classic Chassis";
        return this;
    }

    @Override
    public CarBuilder fixBody() {
        System.out.println("Assembling body of the classical model");
        this.body = "Classic Body";
        return this;
    }

    @Override
    public CarBuilder paint() {
        System.out.println("Painting body of the classical model");
        this.paint = "Classic White Paint";
        return this;
    }
  
    @Override
    public CarBuilder fixInterior() {
        System.out.println("Setting up interior of the classical model");
        this.interior = "Classic interior";
        return this;
    }

    @Override
		public Car build() {
        Car car = new Car(chassis, body, paint, interior);
        if (car.doQualityCheck()) {
            return car;
        } else {
            System.out.println("Car assembly is incomplete. Can't deliver!");
        }
        return null;
    }

}
      
      



ModernCarBuilder



.





package org.trishinfotech.builder;

public class ModernCarBuilder implements CarBuilder {

    private String chassis;
    private String body;
    private String paint;
    private String interior;

    public ModernCarBuilder() {
        super();
    }

    @Override
    public CarBuilder fixChassis() {
        System.out.println("Assembling chassis of the modern model");
        this.chassis = "Modern Chassis";
        return this;
    }

    @Override
    public CarBuilder fixBody() {
        System.out.println("Assembling body of the modern model");
        this.body = "Modern Body";
        return this;
    }
  
    @Override
    public CarBuilder paint() {
        System.out.println("Painting body of the modern model");
        this.paint = "Modern Black Paint";
        return this;
    }

    @Override
    public CarBuilder fixInterior() {
        System.out.println("Setting up interior of the modern model");
        this.interior = "Modern interior";
        return this;
    }

    @Override
    public Car build() {
        Car car = new Car(chassis, body, paint, interior);
        if (car.doQualityCheck()) {
            return car;
        } else {
            System.out.println("Car assembly is incomplete. Can't deliver!");
        }
        return null;
    }
}
      
      



  SportsCarBuilder



.





package org.trishinfotech.builder;

public class SportsCarBuilder implements CarBuilder {

    private String chassis;
    private String body;
    private String paint;
    private String interior;

    public SportsCarBuilder() {
        super();
    }

    @Override
    public CarBuilder fixChassis() {
        System.out.println("Assembling chassis of the sports model");
        this.chassis = "Sporty Chassis";
        return this;
    }
 
    @Override
    public CarBuilder fixBody() {
        System.out.println("Assembling body of the sports model");
        this.body = "Sporty Body";
        return this;
    }
  
    @Override
    public CarBuilder paint() {
        System.out.println("Painting body of the sports model");
        this.paint = "Sporty Torch Red Paint";
        return this;
    }

    @Override
    public CarBuilder fixInterior() {
        System.out.println("Setting up interior of the sports model");
        this.interior = "Sporty interior";
        return this;
    }

    @Override
    public Car build() {
        Car car = new Car(chassis, body, paint, interior);
        if (car.doQualityCheck()) {
            return car;
        } else {
            System.out.println("Car assembly is incomplete. Can't deliver!");
        }
        return null;
    }

}
      
      



4: - AutomotiveEngineer



, ( Car



) .





package org.trishinfotech.builder;

public class AutomotiveEngineer {

    private CarBuilder builder;

    public AutomotiveEngineer(CarBuilder builder) {
        super();
        this.builder = builder;
        if (this.builder == null) {
            throw new IllegalArgumentException("Automotive Engineer can't work without Car Builder!");
        }
    }

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

}
      
      



  , manufactureCar



.





Main



.





package org.trishinfotech.builder;

public class Main {

    public static void main(String[] args) {
        CarBuilder builder = new SportsCarBuilder();
        AutomotiveEngineer engineer = new AutomotiveEngineer(builder);
        Car car = engineer.manufactureCar();
        if (car != null) {
            System.out.println("Below car delievered: ");
            System.out.println("======================================================================");
            System.out.println(car);
            System.out.println("======================================================================");
        }
    }

}
      
      



  :





Assembling chassis of the sports model
Assembling body of the sports model
Painting body of the sports model
Setting up interior of the sports model
Below car delievered: 
======================================================================
Car [chassis=Sporty Chassis, body=Sporty Body, paint=Sporty Torch Red Paint, interior=Sporty interior]
======================================================================
      
      



  , , Builder



. (Abstract Factory), . , . , «», - «».





  : Real-Builder-Design-Pattern-Source-Code





Builder



. , Builder



. , , , Java 8.





Builder



, .





Employee



, .





public class Employee {

    private int empNo;
    private String name;
    private String depttName;
    private int salary;
    private int mgrEmpNo;
    private String projectName;
}
      
      



 , EmpNo



EmpName



, - . , .





  1. .





  2. , Employee



    .





, , , - . , null



.





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



  , .





  public Employee(int empNo, String name) {
        super();
        if (empNo <= 0) {
            throw new IllegalArgumentException("Please provide valid employee number.");
        }
        if (name == null || name.trim().isEmpty()) {
            throw new IllegalArgumentException("Please provide employee name.");
        }
        this.empNo = empNo;
        this.name = name;
    }

    public Employee(int empNo, String name, String depttName) {
        this(empNo, name);
        this.depttName = depttName;
    }

    public Employee(int empNo, String name, String depttName, int salary) {
        this(empNo, name, depttName);
        this.salary = salary;
    }

    public Employee(int empNo, String name, String depttName, int salary, int mgrEmpNo) {
        this(empNo, name, depttName, salary);
        this.mgrEmpNo = mgrEmpNo;
    }

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



 , Builder



:





package org.trishinfotech.builder.example;

public class Employee {

    private int empNo;
    private String name;
    private String depttName;
    private int salary;
    private int mgrEmpNo;
    private String projectName;

    public Employee(EmployeeBuilder employeeBuilder) {
        if (employeeBuilder == null) {
            throw new IllegalArgumentException("Please provide employee builder to build employee object.");
        }
        if (employeeBuilder.empNo <= 0) {
            throw new IllegalArgumentException("Please provide valid employee number.");
        }
        if (employeeBuilder.name == null || employeeBuilder.name.trim().isEmpty()) {
            throw new IllegalArgumentException("Please provide employee name.");
        }
        this.empNo = employeeBuilder.empNo;
        this.name = employeeBuilder.name;
        this.depttName = employeeBuilder.depttName;
        this.salary = employeeBuilder.salary;
        this.mgrEmpNo = employeeBuilder.mgrEmpNo;
        this.projectName = employeeBuilder.projectName;
    }

    public int getEmpNo() {
        return empNo;
    }

    public String getName() {
        return name;
    }
    
    public String getDepttName() {
        return depttName;
    }

    public int getSalary() {
        return salary;
    }

    public int getMgrEmpNo() {
        return mgrEmpNo;
    }
    
    public String getProjectName() {
        return projectName;
    }

    @Override
    public String toString() {
        //  StringBuilder     Builder  
        //  java.lang.Appendable
        StringBuilder builder = new StringBuilder();
        builder.append("Employee [empNo=").append(empNo).append(", name=").append(name).append(", depttName=")
                .append(depttName).append(", salary=").append(salary).append(", mgrEmpNo=").append(mgrEmpNo)
                .append(", projectName=").append(projectName).append("]");
        return builder.toString();
    }

    public static class EmployeeBuilder {
        private int empNo;
        protected String name;
        protected String depttName;
        protected int salary;
        protected int mgrEmpNo;
        protected String projectName;

        public EmployeeBuilder() {
            super();
        }
        
        public EmployeeBuilder empNo(int empNo) {
            this.empNo = empNo;
            return this;
        }

        public EmployeeBuilder name(String name) {
            this.name = name;
            return this;
        }

        public EmployeeBuilder depttName(String depttName) {
            this.depttName = depttName;
            return this;
        }

        public EmployeeBuilder salary(int salary) {
            this.salary = salary;
            return this;
        }

        public EmployeeBuilder mgrEmpNo(int mgrEmpNo) {
            this.mgrEmpNo = mgrEmpNo;
            return this;
        }
        public EmployeeBuilder projectName(String projectName) {
            this.projectName = projectName;
            return this;
        }

        public Employee build() {
            Employee emp = null;
            if (validateEmployee()) {
                emp = new Employee(this);
            } else {
                System.out.println("Sorry! Employee objects can't be build without required details");
            }
            return emp;
        }

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



EmployeeBuilder



. Java. .





EmployeeMain



Employee



:





package org.trishinfotech.builder.example;

public class EmployeeMain {

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



, . . (Director), ( ) . , Employee



, .





Builder

, Order () - Order Service Type (Take Away - /Eat Here - ), (Food Items) (Customer Name - ) . . , .





OrderService



:





package org.trishinfotech.builder;

public enum OrderService {

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

    private String name;
    private double tax;

    OrderService(String name, double tax) {
        this.name = name;
        this.tax = tax;
    }

    public String getName() {
        return name;
    }

    public double getTax() {
        return tax;
    }

}
      
      



  FoodItem



:





package org.trishinfotech.builder.meal;

import org.trishinfotech.builder.packing.Packing;

public interface FoodItem {

    public String name();

    public int calories();

    public Packing packing();

    public double price();
}
      
      



  Meal



(). Meal



( ).





package org.trishinfotech.builder.meal;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import org.trishinfotech.builder.packing.MultiPack;
import org.trishinfotech.builder.packing.Packing;

public class Meal implements FoodItem {

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

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

    public List<FoodItem> getFoodItems() {
        return foodItems;
    }

    @Override
    public String name() {
        return mealName;
    }
  
    @Override
    public int calories() {
        int totalCalories = foodItems.stream().mapToInt(foodItem -> foodItem.calories()).sum();
        return totalCalories;
    }

    @Override
    public Packing packing() {
        double packingPrice = foodItems.stream().map(foodItem -> foodItem.packing())
                .mapToDouble(packing -> packing.packingPrice()).sum();
        return new MultiPack(packingPrice);
    }

    @Override
    public double price() {
        double totalPrice = foodItems.stream().mapToDouble(foodItem -> foodItem.price()).sum();
        return totalPrice;
    }

    public double discount() {
        return discount;
    }
}
      
      



:

Burger



:





package org.trishinfotech.builder.food.burger;

import org.trishinfotech.builder.meal.FoodItem;
import org.trishinfotech.builder.packing.Packing;
import org.trishinfotech.builder.packing.Wrap;

public abstract class Burger implements FoodItem {

    @Override
    public Packing packing() {
        return new Wrap();
    }

}
      
      



ChickenBurger



:





package org.trishinfotech.builder.food.burger;

public class ChickenBurger extends Burger {

    @Override
    public String name() {
        return "Chicken Burger";
    }

    @Override
    public int calories() {
        return 300;
    }

    @Override
    public double price() {
        return 4.5d;
    }

}
      
      



VegBurger



( ):





package org.trishinfotech.builder.food.burger;

public class VegBurger extends Burger {

    @Override
    public String name() {
        return "Veg Burger";
    }

    @Override
    public int calories() {
        return 180;
    }

    @Override
    public double price() {
        return 2.7d;
    }

}
      
      



Nuggets



:





package org.trishinfotech.builder.food.nuggets;

import org.trishinfotech.builder.meal.FoodItem;
import org.trishinfotech.builder.packing.Container;
import org.trishinfotech.builder.packing.Packing;

public abstract class Nuggets implements FoodItem {

    @Override
    public Packing packing() {
        return new Container();
    }

}
      
      



  CheeseNuggets



:





package org.trishinfotech.builder.food.nuggets;

public class CheeseNuggets extends Nuggets {

    @Override
    public String name() {
        return "Cheese Nuggets";
    }

    @Override
    public int calories() {
        return 330;
    }

    @Override
    public double price() {
        return 3.8d;
    }

}
      
      



ChickenNuggets



:





package org.trishinfotech.builder.food.nuggets;

public class ChickenNuggets extends Nuggets {

    @Override
    public String name() {
        return "Chicken Nuggets";
    }

    @Override
    public int calories() {
        return 450;
    }

    @Override
    public double price() {
        return 5.0d;
    }

}
      
      



:

. , BeverageSize



:





package org.trishinfotech.builder.beverages;

public enum BeverageSize {
    XS("Extra Small", 110), S("Small", 150), M("Medium", 210), L("Large", 290);
    private String name;
    private int calories;

    BeverageSize(String name, int calories) {
        this.name = name;
        this.calories = calories;
    }
  
    public String getName() {
        return name;
    }

    public int getCalories() {
        return calories;
    }

}
      
      



Drink



:





package org.trishinfotech.builder.beverages;

import org.trishinfotech.builder.meal.FoodItem;

public abstract class Drink implements FoodItem {

    protected BeverageSize size;

    public Drink(BeverageSize size) {
        super();
        this.size = size;
        if (this.size == null) {
            this.size = BeverageSize.M;
        }
    }

    public BeverageSize getSize() {
        return size;
    }

    public String drinkDetails() {
        return " (" + size + ")";
    }
}
      
      



  ColdDrink



:





package org.trishinfotech.builder.beverages.cold;

import org.trishinfotech.builder.beverages.BeverageSize;
import org.trishinfotech.builder.beverages.Drink;
import org.trishinfotech.builder.packing.Bottle;
import org.trishinfotech.builder.packing.Packing;

public abstract class ColdDrink extends Drink {

    public ColdDrink(BeverageSize size) {
        super(size);
    }

    @Override public Packing packing() {
        return new Bottle();
    }
}
      
      



  CocaCola



:





package org.trishinfotech.builder.beverages.cold;

import org.trishinfotech.builder.beverages.BeverageSize;

public class CocaCola extends ColdDrink {

    public CocaCola(BeverageSize size) {
        super(size);
    }

    @Override
    public String name() {
        return "Coca-Cola" + drinkDetails();
    }

    @Override
    public int calories() {
        if (size != null) {
            switch (size) {
            case XS:
                return 110;
            case S:
                return 150;
            case M:
                return 210;
            case L:
                return 290;
            default:
                break;
            }
        }
        return 0;
    }

    @Override
    public double price() {
        if (size != null) {
            switch (size) {
            case XS:
                return 0.80d;
            case S:
                return 1.0d;
            case M:
                return 1.5d;
            case L:
                return 2.0d;
            default:
                break;
            }
        }
        return 0.0d;
    }

}
      
      



Pepsi



:





package org.trishinfotech.builder.beverages.cold;

import org.trishinfotech.builder.beverages.BeverageSize;

public class Pepsi extends ColdDrink {

    public Pepsi(BeverageSize size) {
        super(size);
    }

    @Override public String name() {
        return "Pepsi" + drinkDetails();
    }

    @Override public int calories() {
        if (size != null) {
            switch (size) {
                case S:
                    return 160;
                case M:
                    return 220;
                case L:
                    return 300;
                default:
                    break;
            }
        }
        return 0;
    }

    @Override public double price() {
        if (size != null) {
            switch (size) {
                case S:
                    return 1.2d;
                case M:
                    return 2.2d;
                case L:
                    return 2.7d;
                default:
                    break;
            }
        }
        return 0.0d;
    }

}
      
      



  HotDrink



:





package org.trishinfotech.builder.beverages.hot;

import org.trishinfotech.builder.beverages.BeverageSize;
import org.trishinfotech.builder.beverages.Drink;
import org.trishinfotech.builder.packing.Packing;
import org.trishinfotech.builder.packing.SipperMug;

public abstract class HotDrink extends Drink {

    public HotDrink(BeverageSize size) {
        super(size);
    }
    
    @Override public Packing packing() {
        return new SipperMug();
    }
}
      
      



Cuppuccinno



:





package org.trishinfotech.builder.beverages.hot;

import org.trishinfotech.builder.beverages.BeverageSize;

public class Cappuccino extends HotDrink {

    public Cappuccino(BeverageSize size) {
        super(size);
    }

    @Override public String name() {
        return "Cappuccino" + drinkDetails();
    }
  
    @Override public int calories() {
        if (size != null) {
            switch (size) {
                case S:
                    return 120;
                case M:
                    return 160;
                case L:
                    return 210;
                default:
                break;
            }
        }
        return 0;
    }

    @Override public double price() {
        if (size != null) {
            switch (size) {
                case S:
                    return 1.0d;
                case M:
                    return 1.4d;
                case L:
                    return 1.8d;
                default:
                break;
            }
        }
        return 0.0d;
    }

}
      
      



HotChocolate



:





package org.trishinfotech.builder.beverages.hot;

import org.trishinfotech.builder.beverages.BeverageSize;

public class HotChocolate extends HotDrink {

    public HotChocolate(BeverageSize size) {
        super(size);
    }

    @Override public String name() {
        return "Hot Chocolate" + drinkDetails();
    }
  
    @Override public int calories() {
        if (size != null) {
            switch (size) {
                case S:
                    return 370;
                case M:
                    return 450;
                case L:
                    return 560;
                default:
                    break;
            }
        }
        return 0;
    }
    
    @Override public double price() {
        if (size != null) {
            switch (size) {
                case S:
                    return 1.6d;
                case M:
                    return 2.3d;
                case L:
                    return 3.0d;
                default:
                    break;
            }
          
       }
        return 0.0d;
    }

}
      
      



:

Packing



:





package org.trishinfotech.builder.packing;

public interface Packing {

    public String pack();

    public double packingPrice();
}
      
      



Bottle



:





package org.trishinfotech.builder.packing;

public class Bottle implements Packing {

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

    @Override
    public double packingPrice() {
        return 0.75d;
    }

}
      
      



Container



:





package org.trishinfotech.builder.packing;

public class Container implements Packing {

    @Override
    public String pack() {
        return "Container";
    }

    @Override
    public double packingPrice() {
        return 1.25d;
    }

}
      
      



MultiPack



. MutiPack



, .





package org.trishinfotech.builder.packing;

public class MultiPack implements Packing {

    private double packingPrice;


    public MultiPack(double packingPrice) {
        super();
        this.packingPrice = packingPrice;
    }
  
    @Override
    public String pack() {
        return "Multi-Pack";
    }

    @Override
    public double packingPrice() {
        return packingPrice;
    }

}
      
      



SipperMug



:





package org.trishinfotech.builder.packing;

public class SipperMug implements Packing {

    @Override
    public String pack() {
        return "Sipper Mug";
    }

    @Override
    public double packingPrice() {
        return 1.6d;
    }

}
      
      



Wrap



:





package org.trishinfotech.builder.packing;

public class Wrap implements Packing {

    @Override
    public String pack() {
        return "Wrap";
    }

    @Override
    public double packingPrice() {
        return 0.40d;
    }

}
      
      



BillPrinter



, .





package org.trishinfotech.builder.util;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.atomic.DoubleAdder;

import org.trishinfotech.builder.Order;
import org.trishinfotech.builder.OrderService;
import org.trishinfotech.builder.meal.Meal;
import org.trishinfotech.builder.packing.Packing;

public class BillPrinter {

    static DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");

    public static void printItemisedBill(Order order) {
        OrderService service = order.getService();
        System.out.printf("%60s\n", "Food Court");
        System.out.println("=================================================================================================================");
        System.out.printf("Service: %10s (%2.2f Tax)                                                         Customer Name: %-20s\n", service.getName(), service.getTax(), order.getCustomerName());
        System.out.println("-----------------------------------------------------------------------------------------------------------------");
        System.out.printf("%25s | %10s | %10s | %10s | %15s | %10s | %10s\n", "Food Item", "Calories", "Packing", "Price", "Packing Price", "Discount %", "Total Price");
        System.out.println("-----------------------------------------------------------------------------------------------------------------");
        DoubleAdder itemTotalPrice = new DoubleAdder();
        order.getFoodItems().stream().forEach(item -> {
            String name = item.name();
            int calories = item.calories();
            Packing packing = item.packing();
            double price = item.price();
            double packingPrice = packing.packingPrice();
            double discount = item instanceof Meal? ((Meal)item).discount() : 0.0d;
            double totalItemPrice = calculateTotalItemPrice(price, packingPrice, discount);
            System.out.printf("%25s | %10d | %10s | %10.2f | %15.2f | %10.2f | %10.2f\n", name, calories, packing.pack(), price, packing.packingPrice(), discount, totalItemPrice);
            itemTotalPrice.add(totalItemPrice);
        });
        System.out.println("=================================================================================================================");
        double billTotal = itemTotalPrice.doubleValue();
        billTotal = applyTaxes(billTotal, service);
        System.out.printf("Date: %-30s %66s %.2f\n", dtf.format(LocalDateTime.now()), "Total Bill (incl. taxes):", billTotal);
        System.out.println("Enjoy your meal!\n\n\n\n");
    }

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

    private static double calculateTotalItemPrice(double price, double packingPrice, double discount) {
        if (discount > 0.0d) {
            price = price - (price * discount)/100;
        }
        return price + packingPrice;
    }
}
      
      



. Order



:





package org.trishinfotech.builder;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import org.trishinfotech.builder.meal.FoodItem;

public class Order {

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

    private String customerName;
    private OrderService service;

    public Order(OrderService service, List<FoodItem> foodItems, String customerName) {
        super();
        if (Objects.isNull(service)) {
            throw new IllegalArgumentException(
                    "Meal can't be order without selecting service 'Take Away' or 'Eat Here'");
        }
        if (Objects.isNull(foodItems) || foodItems.stream().filter(Objects::nonNull).collect(Collectors.toList()).isEmpty()) {
            throw new IllegalArgumentException(
                    "Meal can't be order without any food item");
        }
        this.service = service;
        this.foodItems = new ArrayList<FoodItem>(foodItems);
        this.customerName = customerName;
        if (this.customerName == null) {
            this.customerName = "NO NAME";
        }
    }

    public List<FoodItem> getFoodItems() {
        return foodItems;
    }

    public String getCustomerName() {
        return customerName;
    }

    public OrderService getService() {
        return service;
    }

}
      
      



OrderBuilder



, Order



.





package org.trishinfotech.builder;

import java.util.ArrayList;
import java.util.List;

import org.trishinfotech.builder.beverages.BeverageSize;
import org.trishinfotech.builder.beverages.cold.CocaCola;
import org.trishinfotech.builder.beverages.cold.Pepsi;
import org.trishinfotech.builder.food.burger.ChickenBurger;
import org.trishinfotech.builder.food.burger.VegBurger;
import org.trishinfotech.builder.food.nuggets.CheeseNuggets;
import org.trishinfotech.builder.food.nuggets.ChickenNuggets;
import org.trishinfotech.builder.meal.FoodItem;
import org.trishinfotech.builder.meal.Meal;

public class OrderBuilder {

    protected static final double HAPPY_MENU_DISCOUNT = 5.0d;

    private String customerName;

    private OrderService service = OrderService.TAKE_AWAY;

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

    public OrderBuilder() {
        super();
    }
  
    //       .     Order.
    //       Builder (, OrderBuilder),      .
    public OrderBuilder name(String customerName) {
        this.customerName = customerName;
        return this;
    }
  
    public OrderBuilder service(OrderService service) {
        if (service != null) {
            this.service = service;
        }
        return this;
    }

    public OrderBuilder item(FoodItem item) {
        items.add(item);
        return this;
    }

    //   
    public OrderBuilder vegNuggetsHappyMeal() {
        List<FoodItem> foodItems = new ArrayList<FoodItem>();
        foodItems.add(new CheeseNuggets());
        foodItems.add(new Pepsi(BeverageSize.S));
        Meal meal = new Meal("Veg Nuggets Happy Meal", foodItems, HAPPY_MENU_DISCOUNT);
        return item(meal);
    }

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

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

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

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

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



! Main



:





package org.trishinfotech.builder;

import org.trishinfotech.builder.beverages.BeverageSize;
import org.trishinfotech.builder.beverages.cold.CocaCola;
import org.trishinfotech.builder.beverages.cold.Pepsi;
import org.trishinfotech.builder.beverages.hot.HotChocolate;
import org.trishinfotech.builder.food.burger.ChickenBurger;
import org.trishinfotech.builder.food.nuggets.CheeseNuggets;
import org.trishinfotech.builder.food.nuggets.ChickenNuggets;
import org.trishinfotech.builder.util.BillPrinter;

public class Main {

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

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

}
      
      



  :






                                                  Food Court
=================================================================================================================
Service:  Take Away (2.00 Tax)                                                         Customer Name: Brijesh             
-----------------------------------------------------------------------------------------------------------------
                Food Item |   Calories |    Packing |      Price |   Packing Price | Discount % | Total Price
-----------------------------------------------------------------------------------------------------------------
           Chicken Burger |        300 |       Wrap |       4.50 |            0.40 |       0.00 |       4.90
                Pepsi (M) |        220 |     Bottle |       2.20 |            0.75 |       0.00 |       2.95
   Veg Nuggets Happy Meal |        490 | Multi-Pack |       5.00 |            2.00 |       5.00 |       6.75
=================================================================================================================
Date: 2020/10/09 20:02:38                                                     Total Bill (incl. taxes): 14.89
Enjoy your meal!

                                                  Food Court
=================================================================================================================
Service:   Eat Here (5.50 Tax)                                                         Customer Name: Micheal             
-----------------------------------------------------------------------------------------------------------------
                Food Item |   Calories |    Packing |      Price |   Packing Price | Discount % | Total Price
-----------------------------------------------------------------------------------------------------------------
          Chicken Nuggets |        450 |  Container |       5.00 |            1.25 |       0.00 |       6.25
           Cheese Nuggets |        330 |  Container |       3.80 |            1.25 |       0.00 |       5.05
            Coca-Cola (L) |        290 |     Bottle |       2.00 |            0.75 |       0.00 |       2.75
Chicken Burger Happy Meal |        450 | Multi-Pack |       5.50 |            1.15 |       5.00 |       6.38
        Hot Chocolate (M) |        450 | Sipper Mug |       2.30 |            1.60 |       0.00 |       3.90
    Veg Burger Happy Meal |        340 | Multi-Pack |       3.90 |            1.15 |       5.00 |       4.86
=================================================================================================================
Date: 2020/10/09 20:02:38                                                     Total Bill (incl. taxes): 30.78
Enjoy your meal!
      
      



! , Builder.





: Real-Builder-Design-Pattern-Source-Code





: Builder-Design-Pattern-Sample-Code






Β« Β».





Β« GRASPΒ».








All Articles