How to implement the Builder Design Pattern in the right way? - java

I have found different implementations of the Builder pattern when learning about design patterns. Some implementations use an interface/abstract-class to represent the builder, others use just an static class.
Which one is the right way to implement the Builder Design Pattern?
Below, an implementation using an abstract class (ComputerBuilder) (Source)
public class LaptopBuilder : ComputerBuilder
{
Computer computer;
public LaptopBuilder()
{
computer = new Computer("Laptop");
}
public override void BuildOS()
{
//TODO
}
public override void BuildDevice()
{
//TODO
}
public Computer ComputerType
{
get { return computer; }
}
}
public class DesktopBuilder : ComputerBuilder
{
Computer computer;
public DesktopBuilder()
{
computer = new Computer("Desktop");
}
public override void BuildOS()
{
//TODO
}
public override void BuildDevice()
{
//TODO
}
public Computer ComputerType
{
get { return computer; }
}
}
Below, another implementation, Neither using abstract class nor interface, but an static class instead. (Source)
public class User
{
//All final attributes
private final String firstName; // required
private final String lastName; // required
private final int age; // optional
private final String phone; // optional
private final String address; // optional
private User(UserBuilder builder) {
this.firstName = builder.firstName;
this.lastName = builder.lastName;
this.age = builder.age;
this.phone = builder.phone;
this.address = builder.address;
}
//All getter, and NO setter to provde immutability
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public int getAge() {
return age;
}
public String getPhone() {
return phone;
}
public String getAddress() {
return address;
}
#Override
public String toString() {
return "User: "+this.firstName+", "+this.lastName+", "+this.age+", "+this.phone+", "+this.address;
}
public static class UserBuilder
{
private final String firstName;
private final String lastName;
private int age;
private String phone;
private String address;
public UserBuilder(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public UserBuilder age(int age) {
this.age = age;
return this;
}
public UserBuilder phone(String phone) {
this.phone = phone;
return this;
}
public UserBuilder address(String address) {
this.address = address;
return this;
}
//Return the finally consrcuted User object
public User build() {
User user = new User(this);
validateUserObject(user);
return user;
}
private void validateUserObject(User user) {
//Do some basic validations to check
//if user object does not break any assumption of system
}
}
}

If you actually read the second article you may notice that it fairly early on states that
"I want to make it clear that the builder pattern which I am going to discuss in this post, is slightly different from what is mentioned in GangOfFour “Design Patterns” book." (Author's emphasis)
A little later, he or she writes:
"For me, a builder pattern is more like fluent interface."
Notice the little qualifier, for me.
This should tell you that what you see isn't the 'canonical' representation of the pattern, but a variation.
That said, these representations are variations of the same underlying idea.
It's okay to look at alternative ways to express a concept. We should be careful that we don't elevate the Gang of Four book to unassailable status.

For me (pun intended) Builder is the best example of a GoF pattern that has been improved since the book was published. I believe it was Josh Bloch's version from Effective Java that popularized the static approach; but there are versions originating from blog posts that are more useful and/or less complicated than the GoF version.
As often as I refer back to the GoF book, I never reread the Builder chapter, because better alternatives are available. Of course, you have to decide which alternative is better for you.

Related

Use of private data variables in simple POJO [duplicate]

This question already has answers here:
Why use getters and setters/accessors?
(37 answers)
Closed 1 year ago.
Recently I was going through the concept of Encapsulation in Java. I was wondering if making data variables private along with public setter methods really make sense in simple POJO class? Please refer below POJO:
public class Employee{
private String id;
private String name;
private String department;
private int age;
public Employee(){
}
public Employee(String id, String name, String department, int age){
this.id = id;
this.name = name;
this.department = department;
this.age = age;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDepartment() {
return department;
}
public void setDepartment(String department) {
this.department = department;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
I mean why am I making the name variable private when I can anyway change it using the setter method?
In the general case, it'll be the very basic
public void setName(String name) {
this.name = name;
}
Where it's identical to just doing employee.name = "william hammond". But imagine a case where you'd like to do implement something like a private String normalize(string username) method where you maybe make it all lower case, check for a valid name or prevent unicode entries. If you make name public initially you'll have users doing employee.name = "whatever they want :) 123" and you'll lose the ability to enforce that constraint.
Also see Why use getters and setters/accessors?
Using getters/setters is just considered good practice, but it can often be overkill - like in your example.
If you have methods that mutate the variable before setting, then it's nice to have getters/setters for the basic fields as well to maintain consistent code style.
Here's a good article on it:
https://dzone.com/articles/getter-setter-use-or-not-use-0
Let's have an example:
public class Example {
private String firstName;
private String lastName;
public Example(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public String getFullName() {
return firstName + " " + lastName;
}
}
This class has 3 properties (firstName, lastName, fullName), but only two fields (firstName, lastName). It makes sense, because a full name can be retrieved by combining first and last name.
However, I've noticed that I call getFullName() a lot of times in my program, but I almost never call getFirstName() and getLastName(). This slows down my program, because I need to create a new string each time getFullName() is called. So, I've refactored my code to have a better performance:
public class Example {
private String fullName;
public Example(String firstName, String lastName) {
this.fullName = firstName + " " + lastName;
}
public String getFirstName() {
return fullName.split(" ")[0];
}
public String getLastName() {
return fullName.split(" ")[1];
}
public String getFullName() {
return fullName;
}
}
Now my code works faster when calling getFullName(), but slower when calling getFirstName() and getLastName(), however It's exactly what I needed. From outside the class, nothing really've changed.
As you can see by the given example, fields describe how your class uses the computer's memory, but not necessarily which properties your class has. This is why fields should be considered an implementation detail and therefore be private to a class.

using enum with pattern builder in java

im trying to learn how to use pattern builder. i could get it to work until i tried to use enum.
I tried to change the code couple of times and each time had different error. right now the error is Incompatible types.
Please can you help bringing this code to working state and if you have suggestions to improve the code it would be great.
thanks.
EDIT:
now it seems to be okay, but how do i use it with the builder inside the main?
this was the code i used
main:
Person person3 = new Person.PersonBuilder("Julliete", "Kaplan" )
.status(); // what should i write here to set the status?
person class
public class Person
{
private final String name;
private final String lastname;
private final int age;
//My enum im trying to use
private Status status;
public enum Status
{
SINGLE ("Single"), MARRIED ("Married"), WIDOWER ("Widower");
private String status;
private Status(String status)
{
this.status = status;
}
public String getStatus()
{
return this.status;
}
}
//builder
private Person(PersonBuilder builder) {
this.name = builder.name;
this.lastname = builder.lastname;
this.age = builder.age;
this.status = builder.status;
}
//GETTERS
public String getName() {
return name;
}
public String getLastname() {
return lastname;
}
public int getAge() {
return age;
}
#Override
public String toString() {
return "Person : "+this.name+", "+this.lastname+", "+this.age;
}
//PersonBuilder
public static class PersonBuilder
{
private final String name;
private final String lastname;
private int age;
private Status status;
public PersonBuilder(String name, String lastname) {
this.name = name;
this.lastname = lastname;
}
public PersonBuilder age(int age) {
this.age = age;
return this;
}
public PersonBuilder status(Status status)
{
this.status = status;
return this;
}
public Person build() {
Person person = new Person(this);
return person;
}
}
Don't define another Status enum inside the builder: reuse the one defined in the Person class.
Otherwise, you've got to map from instances of PersonBuilder.Status to instances of Person.Status: they are entirely separate types.
Currently this mapping is trivial: you can use Person.Status.valueOf(personBuilderStatus.name()) - but you have to ensure that you update both at the same time to have identical values (or at least that PersonBuilder.Status maps to a subset of Person.Status), which is an unnecessary maintenance burden going forwards.

Understanding how to decouple

I've been trying to keep coupling down in my code, but I think I may not fully understand it. My basic understanding is that coupling is "how dependent classes are on each other and know about the behavior of each other." I know that dependency injection is one way to reduce coupling and IoC.
The following is an quick example I came up of a Student, Professor, and Course. A course has a list of students and a professor. I have a controller (using MVC) that injects the Student and Professor objects.
Would the following still be considered coupled, or tightly coupled? This also would be an example of DI, correct?
Student class
public class Student {
private String firstName;
private String lastName;
private int studentID;
private int address;
private int telephone;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public int getStudentID() {
return studentID;
}
public void setStudentID(int studentID) {
this.studentID = studentID;
}
public int getAddress() {
return address;
}
public void setAddress(int address) {
this.address = address;
}
public int getTelephone() {
return telephone;
}
public void setTelephone(int telephone) {
this.telephone = telephone;
}
}
Professor Class
public class Professor {
private String firstName;
private String lastName;
private int professorID;
private int address;
private int telephone;
private int salary;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public int getProfessorID() {
return professorID;
}
public void setProfessorID(int professorID) {
this.professorID = professorID;
}
public int getAddress() {
return address;
}
public void setAddress(int address) {
this.address = address;
}
public int getTelephone() {
return telephone;
}
public void setTelephone(int telephone) {
this.telephone = telephone;
}
public int getSalary() {
return salary;
}
public void setSalary(int salary) {
this.salary = salary;
}
}
Course Class
import java.util.List;
public class Course {
private List<Student> students;
private Professor professor;
public Professor getProfessor() {
return professor;
}
public void setProfessor(Professor professor) {
this.professor = professor;
}
public List<Student> getStudents() {
return students;
}
public void setStudents(List<Student> students) {
this.students = students;
}
}
I have a controller (using MVC) that injects the Student and Professor objects. Would the following still be considered coupled, or tightly coupled?
Since all references are Classes, you have a tightly coupled design. A good approach is to use interfaces in your code. This will allow you to change implementation any time you want and it will not affect the rest of your application.
This also would be an example of DI, correct?
If your Course, Professor and Student are configured beans, and you specify somewhere how to inject instances during bean instantiation, it will be a DI example. By now it is just three POJO classes.
What you have put here seem to be the Model part of your MVC implementation which have limited functionality other than setter-getters. To have a good example of decoupling and DI, you probably have Model, View and Controller classes that implement some interfaces. They are decoupled as each class's implementation is not aware/dependent on the other implementations. They only relate based on interfaces that well encapsulate and isolate components.
Probably you also have some fake/test implementation of those interfaces too
Then, there is a IoC setup that controls what implementation of each component will be resolved.

What are the disadvantages of my implementation of the builder object?

I want to know if my implementation of the builder object has disadvantages compared to the builder object implementation I see on most site's. I know it's overkill to implement a builder object for a class with only 2 fields, but these are just examples and meant to be small.
My implementation:
public class User {
private String firstname;
private String lastname;
public String getFirstname() {
return firstname;
}
public String getLastname() {
return lastname;
}
private User(){}
public static class Builder{
private final User user;
public Builder(){
user = new User();
}
public Builder firstname(String firstname){
user.firstname = firstname;
return this;
}
public Builder lastname(String lastname){
user.lastname = lastname;
return this;
}
public User build(){
return user;
}
}
}
Builder object as found on the internet (example1 example2):
public class User {
private String firstname;
private String lastname;
public String getFirstname() {
return firstname;
}
public String getLastname() {
return lastname;
}
private User(Builder builder){
this.firstname = builder.firstname;
this.lastname = builder.lastname;
}
public static class Builder{
private String firstname;
private String lastname;
public Builder firstname(String firstname){
this.firstname = firstname;
return this;
}
public Builder lastname(String lastname){
this.lastname = lastname;
return this;
}
public User build(){
return new User(this);
}
}
}
The second implementations seems cumbersome, cause the builder needs to have exactly the same field as the object it will be building (read: writing the same code twice).
It also seems more naturally (to me) that the builder creates the new User and populates its fields, instead off calling the constructor of the User with it's own instance.
Both examples can be tested with:
public static void main(String[] args) {
User u = new User.Builder().firstname("Tom").lastname("Jonckheere").Build();
System.out.println(u.getFirstname());
System.out.println(u.getLastname());
}
So my question is:
What are the disadvantages of my implementation of the builder object? I can't really tell any (and I'm not saying there aren't any) so I would like to hear some feedback! Or is my code also a valid implementation of the builder object?
The difference in the implementations are that if you want to create multiple equal (or similar) but not same objects, you'll have to create a new Builder whereas with the other implementation you can do this:
Builder b = new User.Builder();
User john = b.firstName("John").lastName("Smith").build();
User jack = b.firstName("Jack").build();

Get and set to private variables in java

Good day,
I am new to JAVA'm learning this language and what I have learned it seems a fantastic language. My question is in relation to the following:
Suppose I have a class like this:
public class Person{
private String firstName;
private String lastName;
private int age;
private String entireName;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getEntireName() {
return entireName;
}
public void setEntireName(String entireName) {
this.entireName = entireName;
}
public static void Main(String args[]){
Person person = new Person();
person.setFirstName("Jhon");
person.setLastName("Adams");
person.setAge(20);
//Atention this line
person.setEntireName(person.getFirstName()+person.getLastName());
}
}
The language allows me to do this: person.setEntireName(person.getFirstName()+person.getLastName());
and it works fine however I would like to know how is best to do this, how it behaves at the object level and how high or low the performance.
Thank you ..
What you do is perfectly valid, but not very logical. Why not just drop the setEntireName() since it just combines two existing fields?
public String getEntireName() {
return firstName + " " + lastname;
}
This is valid. There is no performance difference, becasue JIT compiler optimize this code if needed (simply replace method with fields access).
Typically it is easier to eliminate the entireName property and its setter, and use the getter to perform the concatenation like so:
public String getEntireName() {
return firstName + " " + lastName;
}
This is also easier to maintain than updating entireName every time firstName or lastName is changed.

Categories

Resources