Thursday, 5 December 2013

Builder Design pattern - Implementation [Animal Toy]

Master Software Architecture & Clean Code!

Subscribe to Ram N Java for clean code, design pattern implementations, and practical Java tutorials!

SUBSCRIBE NOW

Understanding the Builder Design Pattern

The Builder Design Pattern is a creational design pattern that allows you to construct complex objects step by step. When building complex domain models—such as customizable animal toys with distinct heads, bodies, legs, and colors—relying on massive constructors (the telescoping constructor anti-pattern) makes code difficult to read, maintain, and test.

By separating the construction process from the actual product representation, the Builder pattern enables the exact same construction sequence to create different variations of a complex object.

Complete Java Code Walkthrough

Here is an end-to-end, clean implementation demonstrating how to build animal toys step-by-step using the Builder design pattern in Java:

// 1. Product Class
class AnimalToy {
    private String head;
    private String body;
    private String legs;
    private String sound;

    public void setHead(String head) { this.head = head; }
    public void setBody(String body) { this.body = body; }
    public void setLegs(String legs) { this.legs = legs; }
    public void setSound(String sound) { this.sound = sound; }

    @Override
    public String toString() {
        return "AnimalToy [head=" + head + ", body=" + body + ", legs=" + legs + ", sound=" + sound + "]";
    }
}

// 2. Builder Interface
interface AnimalToyBuilder {
    void buildHead();
    void buildBody();
    void buildLegs();
    void buildSound();
    AnimalToy getToy();
}

// 3. Concrete Builder: Lion Toy
class LionToyBuilder implements AnimalToyBuilder {
    private AnimalToy toy = new AnimalToy();

    @Override
    public void buildHead() { toy.setHead("Lion Mane Head"); }

    @Override
    public void buildBody() { toy.setBody("Golden Fur Body"); }

    @Override
    public void buildLegs() { toy.setLegs("4 Strong Paws"); }

    @Override
    public void buildSound() { toy.setSound("Roar!"); }

    @Override
    public AnimalToy getToy() { return this.toy; }
}

// 4. Concrete Builder: Elephant Toy
class ElephantToyBuilder implements AnimalToyBuilder {
    private AnimalToy toy = new AnimalToy();

    @Override
    public void buildHead() { toy.setHead("Elephant Trunk & Ears Head"); }

    @Override
    public void buildBody() { toy.setBody("Grey Tough Body"); }

    @Override
    public void buildLegs() { toy.setLegs("4 Pillar Legs"); }

    @Override
    public void buildSound() { toy.setSound("Trumpet!"); }

    @Override
    public AnimalToy getToy() { return this.toy; }
}

// 5. Director Class
class ToyCreator {
    private AnimalToyBuilder builder;

    public ToyCreator(AnimalToyBuilder builder) {
        this.builder = builder;
    }

    public void assembleToy() {
        builder.buildHead();
        builder.buildBody();
        builder.buildLegs();
        builder.buildSound();
    }

    public AnimalToy getToy() {
        return builder.getToy();
    }
}

// 6. Client Application
public class AnimalToyDemo {
    public static void main(String[] args) {
        // Build a Lion Toy
        AnimalToyBuilder lionBuilder = new LionToyBuilder();
        ToyCreator lionCreator = new ToyCreator(lionBuilder);
        lionCreator.assembleToy();
        AnimalToy lionToy = lionCreator.getToy();
        System.out.println("Created: " + lionToy);

        // Build an Elephant Toy
        AnimalToyBuilder elephantBuilder = new ElephantToyBuilder();
        ToyCreator elephantCreator = new ToyCreator(elephantBuilder);
        elephantCreator.assembleToy();
        AnimalToy elephantToy = elephantCreator.getToy();
        System.out.println("Created: " + elephantToy);
    }
}

Key Architectural Advantages

  • Step-by-Step Construction: Breaks down complex assembly pipelines into discrete, readable, and manageable methods.
  • Single Responsibility Principle: Isolates complex construction logic from the domain representation (AnimalToy).
  • Reusability with Director: The ToyCreator controls the execution sequence, allowing different builders to generate completely different products using the exact same assembly process.

Watch More Related Design Pattern Tutorials


Click here to watch in Youtube : https://www.youtube.com/watch?v=zgPpKTUYux8

Click the below Image to Enlarge
Builder Design pattern - Implementation [Animal Toy]


Builder Design pattern - Implementation [Animal Toy] - Class Diagram

AnimalToy.java

public class AnimalToy
{

private String animalToyName;
private String animalToyHead;
private String animalToyBody;
private String animalToyArms;
private String animalToyLegs;
private String animalToyTail;

public String getAnimalToyName()
{
return animalToyName;
}

public void setAnimalToyName( String animalToyName )
{
this.animalToyName = animalToyName;
}

public String getAnimalToyHead()
{
return animalToyHead;
}

public void setAnimalToyHead( String animalToyHead )
{
this.animalToyHead = animalToyHead;
}

public String getAnimalToyBody()
{
return animalToyBody;
}

public void setAnimalToyBody( String animalToyBody )
{
this.animalToyBody = animalToyBody;
}

public String getAnimalToyArms()
{
return animalToyArms;
}

public void setAnimalToyArms( String animalToyArms )
{
this.animalToyArms = animalToyArms;
}

public String getAnimalToyLegs()
{
return animalToyLegs;
}

public void setAnimalToyLegs( String animalToyLegs )
{
this.animalToyLegs = animalToyLegs;
}

public String getAnimalToyTail()
{
return animalToyTail;
}

public void setAnimalToyTail( String animalToyTail )
{
this.animalToyTail = animalToyTail;
}

@Override
public String toString()
{
return "AnimalToy [animalToyName=" + animalToyName + ", animalToyHead=" + animalToyHead
               + ", animalToyBody=" + animalToyBody + ", animalToyArms=" + animalToyArms
               + ", animalToyLegs=" + animalToyLegs + ", animalToyTail=" + animalToyTail + "]\n";
}

}

AnimalToyBuilder.java

public abstract class AnimalToyBuilder
{
private AnimalToy animalToy;

public AnimalToy getAnimalToy()
{
return animalToy;
}

public void setAnimalToy( AnimalToy animalToy )
{
this.animalToy = animalToy;
}

public final AnimalToy buildAnimalToy()
{
AnimalToy animalToy = createAnimalToy();
setAnimalToy(animalToy);
buildAnimalHead();
buildAnimalBody();
buildAnimalLegs();
buildAnimalArms();
buildAnimalTail();
setAnimalToyName();
return animalToy;
}

public abstract void buildAnimalHead();

public abstract void buildAnimalBody();

public abstract void buildAnimalLegs();

public abstract void buildAnimalArms();

public abstract void buildAnimalTail();

public abstract void setAnimalToyName();

public abstract AnimalToy createAnimalToy();
}

DogToyBuilder.java

public class DogToyBuilder extends AnimalToyBuilder
{
public AnimalToy createAnimalToy()
{
return new AnimalToy();

}

public void buildAnimalHead()
{
getAnimalToy().setAnimalToyHead("Dog head");
System.out.println("Step 1 : Dog Head has been built");

}

public void buildAnimalBody()
{
getAnimalToy().setAnimalToyBody("Dog Body");
System.out.println("Step 2 : Dog Body has been built");

}

public void buildAnimalLegs()
{
getAnimalToy().setAnimalToyLegs("Dog 4 legs");
System.out.println("Step 3 : Dog Legs has been built");
}

public void buildAnimalArms()
{
// No implementation because dog doesn't have Arms
getAnimalToy().setAnimalToyLegs("No arms");
System.out.println("Step 4 : is skiped because dog doesn't have Arms");
}

public void setAnimalToyName()
{
getAnimalToy().setAnimalToyName("Dog");
}

public void buildAnimalTail()
{
getAnimalToy().setAnimalToyTail("Dog Tail");
System.out.println("Step 5 : Dog Tail has been built");
}
}

LionToyBuilder.java

public class LionToyBuilder extends AnimalToyBuilder
{
public AnimalToy createAnimalToy()
{
return new AnimalToy();
}

public void buildAnimalHead()
{
getAnimalToy().setAnimalToyHead("Lion head");
System.out.println("Step 1 : Lion Head has been built");

}

public void buildAnimalBody()
{
getAnimalToy().setAnimalToyBody("Lion Body");
System.out.println("Step 2 : Lion Body has been built");

}

public void buildAnimalLegs()
{
getAnimalToy().setAnimalToyLegs("Lion 4 legs");
System.out.println("Step 3 : Lion Legs has been built");
}

public void buildAnimalArms()
{
// No implementation because Lion doesn't have Arms
getAnimalToy().setAnimalToyLegs("No arms");
System.out.println("Step 4 : is skiped because Lion doesn't have Arms");
}

public void setAnimalToyName()
{
getAnimalToy().setAnimalToyName("Lion");
}

public void buildAnimalTail()
{
getAnimalToy().setAnimalToyTail("Lion Tail");
System.out.println("Step 5 : Lion Tail has been built");
}
}

MonkeyToyBuilder.java

public class MonkeyToyBuilder extends AnimalToyBuilder
{
public AnimalToy createAnimalToy()
{
return new AnimalToy();
}

public void buildAnimalHead()
{
getAnimalToy().setAnimalToyHead("Monkey head");
System.out.println("Step 1 : Monkey Head has been built");

}

public void buildAnimalBody()
{
getAnimalToy().setAnimalToyBody("Monkey Body");
System.out.println("Step 2 : Monkey Body has been built");

}

public void buildAnimalLegs()
{
getAnimalToy().setAnimalToyLegs("Monkey 2 legs");
System.out.println("Step 3 : Monkey Legs has been built");
}

public void buildAnimalArms()
{
getAnimalToy().setAnimalToyArms("Monkey 2 Arms");
System.out.println("Step 4 : Monkey Arms has been built");
}

public void setAnimalToyName()
{
getAnimalToy().setAnimalToyName("Monkey");
}

public void buildAnimalTail()
{
getAnimalToy().setAnimalToyTail("Monkey Tail");
System.out.println("Step 5 : Monkey Tail has been built");
}
}

ToyMaker.java

public class ToyMaker
{
public final static String LION_TOY   = "Lion";
public final static String DOG_TOY    = "Dog";
public final static String MONKEY_TOY = "Monkey";

public static AnimalToy makeToy( String toyType ) throws Exception
{

AnimalToyBuilder animalToyBuilder = null;

if( toyType.equalsIgnoreCase(LION_TOY) )
{
animalToyBuilder = new LionToyBuilder();
}
else if( toyType.equalsIgnoreCase(DOG_TOY) )
{
animalToyBuilder = new DogToyBuilder();
}
else if( toyType.equalsIgnoreCase(MONKEY_TOY) )
{
animalToyBuilder = new MonkeyToyBuilder();
}
else
{
System.out.println("Sorry we cann't make :  " + toyType);
throw new Exception("Sorry we cann't make :  " + toyType);
}
return animalToyBuilder.buildAnimalToy();
}
}

BuilderClient.java

public class BuilderClient
{

public static void main( String[] args ) throws Exception
{
AnimalToy lionToy = ToyMaker.makeToy(ToyMaker.LION_TOY);
System.out.println(lionToy);
AnimalToy dogToy = ToyMaker.makeToy(ToyMaker.DOG_TOY);
System.out.println(dogToy);
AnimalToy monkeyToy = ToyMaker.makeToy(ToyMaker.MONKEY_TOY);
System.out.println(monkeyToy);

}

}

Output
Step 1 : Lion Head has been built
Step 2 : Lion Body has been built
Step 3 : Lion Legs has been built
Step 4 : is skiped because Lion doesn't have Arms
Step 5 : Lion Tail has been built
AnimalToy [animalToyName=Lion, animalToyHead=Lion head, animalToyBody=Lion Body, animalToyArms=null, animalToyLegs=No arms, animalToyTail=Lion Tail]

Step 1 : Dog Head has been built
Step 2 : Dog Body has been built
Step 3 : Dog Legs has been built
Step 4 : is skiped because dog doesn't have Arms
Step 5 : Dog Tail has been built
AnimalToy [animalToyName=Dog, animalToyHead=Dog head, animalToyBody=Dog Body, animalToyArms=null, animalToyLegs=No arms, animalToyTail=Dog Tail]

Step 1 : Monkey Head has been built
Step 2 : Monkey Body has been built
Step 3 : Monkey Legs has been built
Step 4 : Monkey Arms has been built
Step 5 : Monkey Tail has been built
AnimalToy [animalToyName=Monkey, animalToyHead=Monkey head, animalToyBody=Monkey Body, animalToyArms=Monkey 2 Arms, animalToyLegs=Monkey 2 legs, animalToyTail=Monkey Tail]


See also:

  • Builder Design Pattern - Introduction
  • Builder Design pattern - Real Time Example [Meal Package]
  • Builder Design pattern - Real Time Example [Animal Toys]
  • Builder Design pattern - Real Time Example [Beverage]
  • Builder Design Pattern - Class Diagram
  • Builder Design Pattern - Sequence Diagram
  • Builder Design Pattern - Implementation [Beverage]
  • Builder Design Pattern - KeyPoints
  • All Design Patterns Links
  • 1 comment:

    1. There are extremely a couple of kinds of against Belling gadgets that you can disregard, each with their own particular preferences and disservices. A standout amongst the wildest dogs barking devices is the shocking removed. It is trusted that this gadget is intense in light of the fact that it attempts to incur pain on the dog at each point the dog tries to bark. Regardless, there are other individuals who assume that shocking collars consummately get ready gear as long as they are not messed with. Everything is the recommended things here
      for more info visit: best anti dog bark control devices review

      ReplyDelete

    Tutorials