Search code examples
javabuilder-pattern

How to build abstract classes using builder pattern?


This the abstract class I have

public abstract class AbstractActionModel implements IActionModel{
    public abstract void getModel();
    public abstract void getAction();
}

Then I want to use this abstract class like below :

this.getActions().put("sth", AbstractActionModel.builder().action("sth").build());

Since I can not instantiate an abstract class the builder pattern wont work.I don't know any alternative patterns for doing this either.

Note: Also I have no knowledge of classes extended from this base class.


Solution

  • If you want to write a builder without knowledge of the concrete subclasses, the caller of your code will have to supply information about which subclass to create - either by providing an actual class object, or registering a set of classes with names. For example:

    public class Builders
    {
    
        public static abstract class AbstractActionModel
        {
            public abstract void getModel();
    
            public abstract void getAction();
            public abstract void setAction(String action);
        }
    
        public static class ConcreteActionModel extends AbstractActionModel
        {
            public void getModel() {};
    
            public void getAction() {};
            public void setAction(String action) {};
        }
    
        public static class ModelBuilder
        {
            AbstractActionModel model;
    
            Map<String, Class<? extends AbstractActionModel>> register = new HashMap<String, Class<? extends AbstractActionModel>>();
            public void register(String key, Class<? extends AbstractActionModel> c) {register.put("concrete", ConcreteActionModel.class);}
    
            public ModelBuilder choose(String key) throws InstantiationException, IllegalAccessException {          
                model = register.get(key).newInstance();
                return this;
            }
    
            public ModelBuilder action(String action) {
                model.setAction(action);
                return this;
            }
    
            public AbstractActionModel build() {
                return model;
            }
        }
    
        public static void main(String[] args) throws Exception
        {       
            ModelBuilder mb = new ModelBuilder();
            mb.register("concrete", ConcreteActionModel.class);
            mb.choose("concrete").action("sth").build();
        }
    }
    

    Note that the abstract class will need setter methods adding, so that the builder can update properties without knowing the concrete subclass.

    Alternatively, you could use reflection to inspect the subclass and call its methods.