Skip to content
Home » Blog » Builder design pattern

Builder design pattern

Continuing the series of entries about design patterns, I decided to take a builder design pattern to the workshop. This pattern is a creative pattern that can significantly simplify the application code, make it more transparent, and at the same time make us get a very simple tool for developing our application. I invite you to read.

When and why exactly the builder?

The builder pattern can be used when we need to implement in our application the creation of objects that are structurally very similar to each other, but have different implementations. In addition, this pattern allows you to create objects in a stepwise manner. It is best if we try to present the problem with a simple example of creating a bolt object.

The screw seems to be a very simple item, but the multitude of its types makes it not easy to create one class that would be able to easily describe many of its types. Let's take an example of the features that a screw can have:

  • thread size
  • thread type
  • thread length
  • bolt length
  • head shape
  • coating
  • type of coating
  • strength class,
  • left or right-handedness,
  • thread pitch,
  • the material from which it is made,
  • etc.

If we wanted to create an example constructor of our screw, we would have a nice monster that could look like this.

 Sruba srubaPierwsza = new Sruba(6, "metryczna", 20, "walcowy z gniazdem sześciokątnym", "ocynk", "8.8", "prawoskretna", "normalny");

One such constructor could get over and overwork with filling it, but what to do if we would like to use many screws that would only differ in length, eg M6x15, M6x20, M6x30. It would be best if someone or something would fill such a constructor for us.

Let's build a builder

So let's create a builder class for our screw-class facilities.

Bolt class

package com.company;

public class Sruba {
    private double rozmiarGwintu;
    private String typ;
    private double dlugosc;
    private String typLba;
    private String pokrycie;
    private String klasa;
    private String skretnosc;
    private String skok;

   //setters and getters

    }

Bulider class

package com.company;

public class SrubaTyp1 {
    Sruba sruba;

    public SrubaTyp1(double rozmiar, double dlugosc){
        sruba = new Sruba();
        sruba.setRozmiarGwintu(rozmiar);
        sruba.setTyp("metryczna");
        sruba.setDlugosc(dlugosc);
        sruba.setTypLba("walcowy z gniazdem sześciokątnym");
        sruba.setPokrycie("ocynk");
        sruba.setKlasa("8.8");
        sruba.setSkretnosc("prawoskrestna");
        sruba.setSkok("normalny");
    }

    public Sruba getSruba() {
        return sruba;
    }
}

Note that now to create multiple type 1 bolts, all you need to do is create a type 1 bolt builder object and a Bolt class object to which we will assign the result of the builder's work as in the example below:

package com.company;

public class Main {

    public static void main(String[] args) {
        SrubaTyp1 budowniczy1 = new SrubaTyp1(6,20);
        Sruba sruba1 = budowniczy1.getSruba();

        budowniczy1.setDlugoscSrubby(25); //zmieniam tylko długość
        Sruba sruba2 = budowniczy1.getSruba(); //tworzę kolejną śrubę o nowej dlugosci

    }
}

See how elegant solution we have received. Instead of creating many long, hardly readable constructors, we created a class that creates objects of the Bolt class for us. Similarly to the SrubaTyp1 class, you can create subsequent SrubaTyp2, SrubaTyp3 classes, etc. To ensure consistency and correct creation of the Sruba class objects, let's create an interface that will have to be implemented in each builder class of the Sruba class.

package com.company;

public interface SrubaTypy {
    public void setRozmiarSruby(double rozmiarSruby);

    public void setTyp(String typ);

    public void setDlugosc(double dlugosc);

    public void setTypLba(String typLba);

    public void setPokrycie(String pokrycie);

    public void setKlasa(String klasa);

    public void setSkretnosc(String skretnosc);

    public void setSkok(String skok);
}

Having such an interface, I change the SrubaTyp1 class so that it implements the interface written above:

package com.company;

public class SrubaTyp1 implements SrubaTypy {
    Sruba sruba;

    public SrubaTyp1(double rozmiar, double dlugosc) {
        sruba = new Sruba();
        setRozmiarSruby(rozmiar);
        setTyp("metryczna");
        setDlugosc(dlugosc);
        setTypLba("walcowy z gniazdem sześciokątnym");
        setPokrycie("ocynk");
        setKlasa("8.8");
        setSkretnosc("prawoskrestna");
        setSkok("normalny");
    }

    public Sruba getSruba() {
        return sruba;
    }

    @Override
    public void setRozmiarSruby(double rozmiar) {
        sruba.setRozmiarGwintu(rozmiar);
    }

    @Override
    public void setTyp(String typ) {
        sruba.setTyp(typ);
    }

    @Override
    public void setDlugosc(double dlugosc) {
        sruba.setDlugosc(dlugosc);
    }

    @Override
    public void setTypLba(String typLba) {
        sruba.setTypLba(typLba);
    }

    @Override
    public void setPokrycie(String pokrycie) {
        sruba.setPokrycie("ocynk");
    }

    @Override
    public void setKlasa(String klasa) {
        sruba.setKlasa(klasa);
    }

    @Override
    public void setSkretnosc(String skretnosc) {
        sruba.setSkretnosc(skretnosc);
    }

    @Override
    public void setSkok(String skok) {
        sruba.setSkok(skok);
    }
}

Notice that now we have a situation where the constructor creates the Bolts object for us and automatically fills in all the fields. In addition, we have the ability to freely change the values of Bolt fields through setters in the builder class. In the present situation, it is the builder himself who oversees the process of creating the bolt.

Let's put a manager on the builder

A builder pattern often uses an additional manager class to oversee the steps and sequence of using builder class methods. This approach makes the code clearer and easier to operate with builders. Let's write down an example of a manager's code:

package com.company;

public class Kierownik {

    public void stworzSrubeTypuPierwszego(SrubaTypy budowniczySruby) {
        budowniczySruby.setDlugosc(20);
        budowniczySruby.setRozmiarSruby(6);
        budowniczySruby.setTypLba("Stożkowy z gniazdem sześciokątnym");
    }

    public void stworzSrubeTypuDrugiego(SrubaTypy budowniczySruby) {
        budowniczySruby.setDlugosc(30);
        budowniczySruby.setKlasa("8.8");
        budowniczySruby.setRozmiarSruby(8);
    }
}

Having a manager who instructs how to create an object of the bolt class, you can slim down the builder builder and then the class will look like this:

package com.company;

public class SrubaTyp1 implements SrubaTypy {
    Sruba sruba;

    public SrubaTyp1(double rozmiar, double dlugosc) {
        sruba = new Sruba();
    }

    public Sruba getSruba() {
        return sruba;
    }

    @Override
    public void setRozmiarSruby(double rozmiar) {
        sruba.setRozmiarGwintu(rozmiar);
    }

    @Override
    public void setTyp(String typ) {
        sruba.setTyp(typ);
    }

    @Override
    public void setDlugosc(double dlugosc) {
        sruba.setDlugosc(dlugosc);
    }

    @Override
    public void setTypLba(String typLba) {
        sruba.setTypLba(typLba);
    }

    @Override
    public void setPokrycie(String pokrycie) {
        sruba.setPokrycie("ocynk");
    }

    @Override
    public void setKlasa(String klasa) {
        sruba.setKlasa(klasa);
    }

    @Override
    public void setSkretnosc(String skretnosc) {
        sruba.setSkretnosc(skretnosc);
    }

    @Override
    public void setSkok(String skok) {
        sruba.setSkok(skok);
    }
}

We gained a lighter builder class constructor, and also separated the bolt creation methodology into a separate class, which gave us clarity and ease in building subsequent implementations of different types of bolt in one place by adding new methods in the manager class. In addition, at this point, we have enabled the user to implement his own order of building the object, and in addition, we can now introduce, for example, conditional instructions in the manager's class, which will supervise the subsequent stages of creating the bolt object.

To use this class structure, let's rebuild our client code:

package com.company;

public class Main {

    public static void main(String[] args) {
        Kierownik kierownik = new Kierownik(); // zatrudniam do pracy kierownika
        SrubaTypy budowniczySrubyPierwszy = new SrubaTyp1(); // zatrudniam pierwszego budowniczego
        SrubaTypy budowniczySrubyDrugi = new SrubaTyp1(); // zatrudniam drugiego budowniczego

        kierownik.stworzSrubeTypuPierwszego(budowniczySrubyPierwszy); //przypisuję do stowrzenia sruby konkretnego budowniczego
        kierownik.stworzSrubeTypuDrugiego(budowniczySrubyDrugi); //przypisuję do stowrzenia sruby konkretnego budowniczego

        Sruba pierwszaSruba = budowniczySrubyPierwszy.getSruba(); // przypisuje do pierwszaSruba efekt pracy budowniczego pierwszego
        Sruba drugaSruba = budowniczySrubyDrugi.getSruba(); // przypisuje do drugaSruba efekt pracy budowniczego drugiego

        System.out.println("---SRUBA PIERWSZA---");
        System.out.println("Rozmiar gwintu: " + pierwszaSruba.getRozmiarGwintu());
        System.out.println("Typ: " + pierwszaSruba.getTyp());
        System.out.println("Dlugosc: " + pierwszaSruba.getDlugosc());
        System.out.println("Typ Lba: " + pierwszaSruba.getTypLba());
        System.out.println("Pokrycie: " + pierwszaSruba.getPokrycie());
        System.out.println("Klasa: " + pierwszaSruba.getKlasa());
        System.out.println("Skretnosc: " + pierwszaSruba.getSkretnosc());
        System.out.println("Skok: " + pierwszaSruba.getSkok());

        System.out.println("---SRUBA DRUGA---");
        System.out.println("Rozmiar gwintu: " + drugaSruba.getRozmiarGwintu());
        System.out.println("Typ: " + drugaSruba.getTyp());
        System.out.println("Dlugosc: " + drugaSruba.getDlugosc());
        System.out.println("Typ Lba: " + drugaSruba.getTypLba());
        System.out.println("Pokrycie: " + drugaSruba.getPokrycie());
        System.out.println("Klasa: " + drugaSruba.getKlasa());
        System.out.println("Skretnosc: " + drugaSruba.getSkretnosc());
        System.out.println("Skok: " + drugaSruba.getSkok());

    }
}

The result of starting the program will be as follows:

---SRUBA PIERWSZA---
Rozmiar gwintu: 6.0
Typ: null
Dlugosc: 20.0
Typ Lba: Stożkowy z gniazdem sześciokątnym
Pokrycie: null
Klasa: null
Skretnosc: null
Skok: null
---SRUBA DRUGA---
Rozmiar gwintu: 8.0
Typ: null
Dlugosc: 30.0
Typ Lba: null
Pokrycie: null
Klasa: 8.8
Skretnosc: null
Skok: null

Process finished with exit code 0

Summary

The Builder Pattern is a moderately complex design pattern, but when used wisely, it adds flexibility to the application and allows the developer to create objects in stages. In addition, the client code is significantly simplified and more transparent, which results, for example, from the lack of the need to create complex and extensive constructors.

The main disadvantage of this pattern is that it requires the creation of additional classes and interfaces, which in some projects may unnecessarily complicate its class structure.

W celu świadczenia usług na najwyższym poziomie stosuję pliki cookies, które będą zamieszczane w Państwa urządzeniu (komputerze, laptopie, smartfonie). W każdym momencie mogą Państwo dokonać zmiany ustawień Państwa przeglądarki internetowej i wyłączyć opcję zapisu plików cookies. Ze szczegółowymi informacjami dotyczącymi cookies na tej stronie można się zapoznać tutaj: View more
Cookies settings
Akceptuj
Blokuj
Privacy policy
Privacy & Cookies policy
Cookie name Active

The privacy policy describes the rules for the processing of information about you, including personal data and cookies, i.e. cookies.


1. General information

  1. This policy applies to the website operating at the url address: www.wojciechsiwek.pl
  2. The website operator and the personal data administrator is: Wojciech Siwek
  3. The operator's e-mail contact address: wojciech.siwek.programista@gmail.com
  4. The operator is the Administrator of your personal data in relation to the data provided voluntarily on the Website.
  5. The website uses personal data for the following purposes:
    • Running a comment system
    • Handling inquiries via the form
  6. The website obtains information about users and their behavior in the following way:
    1. Through data entered voluntarily in forms, which are entered into the Operator's systems.
    2. By saving cookie files in end devices (so-called "cookies").

2. Selected data protection methods used by the Operator

  1. The places of logging in and entering personal data are protected in the transmission layer (SSL certificate). As a result, personal data and login data entered on the website are encrypted on the user's computer and can only be read on the target server.
  2. User passwords are stored in a hashed form. The hash function works in one direction - it is not possible to reverse its operation, which is now a modern standard in the field of storing user passwords.
  3. The operator periodically changes his administrative passwords.
  4. In order to protect data, the Operator regularly makes backup copies.
  5. In order to protect data, an essential element of data protection is regular updating of all software used by the Operator to process personal data, which in particular means regular updates of programming components. The Operator regularly makes backup copies.

3. Hosting

  1. The website is hosted (technically maintained) on the operator's server: NETMARK.

4. Your rights and additional information on how to use the data

  1. In some situations, the Administrator has the right to transfer your personal data to other recipients if it is necessary to perform the contract concluded with you or to fulfill the obligations incumbent on the Administrator. This applies to such groups of recipients:
    • postal operators
    • comment system operators
    • authorized employees and associates who use the data to achieve the purpose of the website
  2. Your personal data processed by the Administrator for no longer than it is necessary to perform the related activities specified in separate regulations (e.g. on accounting). With regard to marketing data, the data will not be processed for more than 3 years.
  3. You have the right to request from the Administrator:
    • access to your personal data,
    • rectifying them,
    • deletion,
    • processing restrictions,
    • and data portability.
  4. You have the right to object to the processing indicated in point 3.3 c) to the processing of personal data in order to perform the legitimate interests pursued by the Administrator, including profiling, while the right to object may not be exercised if there are valid legally justified grounds for processing of your interests, rights and freedoms, in particular establishing, investigating or defending claims.
  5. The Administrator's actions may be appealed against to the President of the Personal Data Protection Office, ul. Stawki 2, 00-193 Warsaw.
  6. Providing personal data is voluntary, but necessary to operate the Website.
  7. In relation to you, actions may be taken consisting in automated decision making, including profiling to provide services under the concluded contract and for the purpose of conducting direct marketing by the Administrator.
  8. Personal data is not transferred from third countries within the meaning of the provisions on the protection of personal data. This means that we do not send them outside the European Union.

5. Information in the forms

  1. Serwis zbiera informacje podane dobrowolnie przez użytkownika, w tym dane osobowe, o ile zostaną one podane.
  2. The website may save information about connection parameters (time stamp, IP address).
  3. The website, in some cases, may save information facilitating the linking of data in the form with the e-mail address of the user filling in the form. In this case, the user's e-mail address appears inside the url of the page containing the form.
  4. The data provided in the form is processed for the purpose resulting from the function of a specific form, eg to process the service request or commercial contact, service registration, etc. Each time the context and description of the form clearly informs what it is used for.

6. Administrator logs

  1. Information on the behavior of users on the website may be subject to logging. These data are used to administer the website.

7. Relevant marketing techniques

  1. The operator uses statistical analysis of website traffic through Google Analytics (Google Inc. based in the USA). The operator does not provide personal data to the operator of this service, but only anonymised information. The service is based on the use of cookies on the user's end device. In terms of information about user preferences collected by the Google advertising network, the user can view and edit information derived from cookies using the tool: https://www.google.com/ads/preferences/

8. Information about cookies

  1. The website uses cookies.
  2. Cookie files (so-called "cookies") are IT data, in particular text files, which are stored on the Website User's end device and are intended for using the Website's pages. Cookies usually contain the name of the website they come from, the storage time on the end device and a unique number.
  3. The entity that places cookies on the Website User's end device and obtains access to them is the Website operator.
  4. Cookies are used for the following purposes:
    1. maintaining the Website user's session (after logging in), thanks to which the user does not have to re-enter the login and password on each subpage of the Website;
    2. achieving the goals set out above in the section "Important marketing techniques";
  5. The Website uses two basic types of cookies: session cookies and persistent cookies. Session cookies are temporary files that are stored on the User's end device until logging out, leaving the website or turning off the software (web browser). Persistent cookies are stored on the User's end device for the time specified in the cookie file parameters or until they are deleted by the User.
  6. Software for browsing websites (web browser) usually allows cookies to be stored on the User's end device by default. Website Users can change the settings in this regard. The web browser allows you to delete cookies. It is also possible to automatically block cookies.Detailed information on this subject can be found in the help or documentation of the web browser.
  7. Restrictions on the use of cookies may affect some of the functionalities available on the Website pages.
  8. Cookies placed on the Website User's end device may also be used by entities cooperating with the Website operator, in particular the following companies: Google (Google Inc. based in the USA), Facebook (Facebook Inc. based in the USA), Twitter (Twitter Inc. based in the USA).

9. Managing cookies - how to express and withdraw consent in practice?

  1. If the user does not want to receive cookies, he may change the browser settings. We reserve that disabling cookies necessary for authentication processes, security, maintaining user preferences may make it difficult, and in extreme cases may prevent the use of websites.
  2. In order to manage cookie settings, select the web browser you use from the list below and follow the instructions:
Save settings
Cookies settings