Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using a builder to build "partially" mutable objects?

I'm having troubles finding out whether using a builder is the right approach when creating a object that's "partially" mutable, i.e. some of the object's properties are variable.

Let's consider this implementation of an IGlass interface. One final mandatory parameter, one optional parameter that can be changed after object creation:

public class SimpleGlass implements IGlass {

    // Mandatory.
    private final int size;

    // Optional.
    private boolean isEmpty;

    private SimpleGlass(SimpleGlassBuilder builder) {
        size = builder.getSize();
        isEmpty = builder.isEmpty();
    }

    @Override
    public int getSize() {
        return size;
    }

    @Override
    public boolean isEmpty() {
        return isEmpty;
    }

    @Override
    public void setEmpty(boolean isEmpty) {
        this.isEmpty = isEmpty;
    }

    public static class SimpleGlassBuilder {

        // Mandatory.
        private final int size;

        // Optional.
        private boolean isEmpty = false;

        public SimpleGlassBuilder(int size) {
            this.size = size;
        }

        public SimpleGlassBuilder setEmpty(boolean isEmpty) {
            this.isEmpty = isEmpty;
            return this;
        }

        public IGlass build() {
            return new SimpleGlass(this);
        }

        public int getSize() {
            return size;
        }

        public boolean isEmpty() {
            return isEmpty;
        }
    }
}

So the builder creates mutable objects, however, whenever a builder is mentioned in programming literature it's about immutable objects.

Is it okay to use a builder in cases like this?

like image 455
htorque Avatar asked Jan 14 '23 15:01

htorque


2 Answers

I would say that a Builder is used for classes with a lot of properties, most of which are optional to specify. Rather than having a million constructors, or one awful constructor, you use a builder and specify just what you need.

new GlassBuilder(16_OZ).withHandle().withLogo(logo).build()

// instead of
new Glass(16_OZ, 
            /* handle? */ true, 
            /* chipped? */ false, 
            /* monogram? */ null, 
            /* something else? */ null, 
            logo);

Mutability is nice at the end, because mutability is nice, but it doesn't actually affect whether the Builder made your life easier.

like image 65
Michael Brewer-Davis Avatar answered Jan 23 '23 00:01

Michael Brewer-Davis


I would leave the "empty" property in the IGlass implementation class but remove it from the builder. There are too many places to set the value. Plus it confuses the issue if you set it in the builder as that only applies to IGlass instances created after that point and only until their 'setEmpty()' method is called.

I suggest you build them and then set the 'empty' property on the newly built object instance.

The purpose of design patterns is to make things easy to talk about and easy to understand. By adding the additional concern of whether the builder or the instance is setting the 'empty' property, things are no longer so easy.

like image 28
Lee Meador Avatar answered Jan 23 '23 00:01

Lee Meador