-2

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
        }
    }
}
Mark Seemann
  • 225,310
  • 48
  • 427
  • 736

2 Answers2

0

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.

Mark Seemann
  • 225,310
  • 48
  • 427
  • 736
0

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.

jaco0646
  • 15,303
  • 7
  • 59
  • 83