El patrón de diseño del constructor en Java

Anticipándonos al inminente inicio del curso "Arquitectura y Patrones de Diseño", compartimos con ustedes la traducción del material.



También invitamos a todos a una lección de demostración abierta
"Plantillas GRASP" . En esta lección, analizaremos la separación funcional de funcionalidades y veremos 9 plantillas GRASP. ¡Únete a nosotros!






, 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