5

Lets say that I have a Composite set up as follows:

public abstract class Element {
    //position, size, etc.

    //element methods

    //setters/getters
}

public class SimpleElement1 extends Element {
    //...
}

public class SimpleElement2 extends Element {
   //...
}

public class CompositeElement extends Element {
     protected List<Element> childrenElements;

     //methods to add/remove/get children
}

Now, how would I go about wrapping this Composite up into a Builder pattern, so that I can simplify client code by enabling it not to care (or care less) about the intricacies of how to link children to their Composite?

Dave Schweisguth
  • 36,475
  • 10
  • 98
  • 121
Nebojša
  • 51
  • 1
  • 2

2 Answers2

4

In your builder, add methods "startComposite" and "endComposite". These methods push a composite onto a stack and remove a composite from the stack. Messages to add elements always add to the top of stack.

    builder.startComposite();
        builder.simpleElement1();
        builder.simpleElement2();
    builder.endComposite();
    builder.startComposite();
        builder.simpleElement2();
    builder.endComposite();

If your builder methods always return the builder, you can eliminate the repetition of the receiver:

    builder.
        startComposite().
            simpleElement1().
            simpleElement2().
        endComposite().
        startComposite().
            simpleElement2().
        endComposite();
David Buck
  • 2,847
  • 15
  • 16
  • Hmm, this might be what I'm looking for. I'll try to work it out during the day to see how it turns out. Thanks for your time. – Nebojša May 04 '12 at 08:52
2

Here is an example of a builder making an animal composite of different animal parts. You should be able to modify it for your particular application.

class BuilderDesignPattern{
     public static void Main(string[] args)
        {
            Kid aKid = new Kid();
            aKid.Name = "Elizabeth";

            AnimalBuilder builderA = new MonkeyBuilder();
            aKid.MakeAnimal(builderA);
            builderA.aAnimal.ShowMe();

            AnimalBuilder builderB = new KittenBuilder();
            aKid.MakeAnimal(builderB);
            builderB.aAnimal.ShowMe();

        }
    }
    public abstract class AnimalBuilder
    {
        public Animal aAnimal;

        public abstract void BuildAnimalHeader();
        public abstract void BuildAnimalBody();
        public abstract void BuildAnimalLeg();
        public abstract void BuildAnimalArm();
        public abstract void BuildAnimalTail();
    }
    public class MonkeyBuilder : AnimalBuilder
    {

        public MonkeyBuilder()
        {
            aAnimal = new Monkey();
        }

        public override void BuildAnimalHeader()
        {
            aAnimal.Head = "Moneky's Head has been built";
        }

        public override void BuildAnimalBody()
        {
            aAnimal.Body = "Moneky's Body has been built";
        }

        public override void BuildAnimalLeg()
        {
            aAnimal.Leg = "Moneky's Leg has been built";
        }

        public override void BuildAnimalArm()
        {
            aAnimal.Arm = "Moneky's Arm has been built";
        }

        public override void BuildAnimalTail()
        {
            aAnimal.Tail = "Moneky's Tail has been built";
        }
    }
    public class KittenBuilder : AnimalBuilder
    {
        public KittenBuilder()
        {
            aAnimal = new Kitten();
        }

        public override void BuildAnimalHeader()
        {
            aAnimal.Head = "Kitten's Head has been built";
        }

        public override void BuildAnimalBody()
        {
            aAnimal.Body = "Kitten's Body has been built";
        }

        public override void BuildAnimalLeg()
        {
            aAnimal.Leg = "Kitten's Leg has been built";
        }

        public override void BuildAnimalArm()
        {
            aAnimal.Arm = "Kitten's Arm has been built";
        }

        public override void BuildAnimalTail()
        {
            aAnimal.Tail = "Kitten's Tail has been built";
        }
    }
    public abstract class Animal
    {
        public BodyPart Head { get; set; }
        public BodyPart Body { get; set; }
        public BodyPart Leg { get; set; }
        public BodyPart Arm { get; set; }
        public BodyPart Tail { get; set; }


        //helper method for demo the Polymorphism, so we can 
        //easily tell what type object it is from client.
        public abstract void Eat();

        //helper method for demo the result from client
        public void ShowMe()
        {
            Console.WriteLine(Head);
            Console.WriteLine(Body);
            Console.WriteLine(Leg);
            Console.WriteLine(Arm);
            Console.WriteLine(Tail);
            Eat();

        }
    }
    public class Monkey : Animal
    {
        //helper method to show monkey's property for demo purpose
        public override void Eat()
        {
            Console.WriteLine("Since I am Monkey, I like to eat banana");
        }
    }
    public class Kitten : Animal
    {
        public override void Eat()
        {
            Console.WriteLine("Since I am Kitten, I like to eat kitten food");
        }
    }
    public class Kid
    {
        public string Name { get; set; }

        //construct process to build an animal object, 
        //after this process completed, a object 
        //will be consider as a ready to use object.
        public void MakeAnimal(AnimalBuilder aAnimalBuilder)
        {
            aAnimalBuilder.BuildAnimalHeader();
            aAnimalBuilder.BuildAnimalBody();
            aAnimalBuilder.BuildAnimalLeg();
            aAnimalBuilder.BuildAnimalArm();
            aAnimalBuilder.BuildAnimalTail();
        }


    }
    public class BodyPart{
        String name= "";
        public BodyPart(String name){
            this.name=name;
        }
    }
}
eabraham
  • 4,094
  • 1
  • 23
  • 29
  • Thanks for a fast answer, but hows Animal composite in here? Maybe I should rephrase a question: Having a structure similar to [this](http://upload.wikimedia.org/wikipedia/commons/thumb/5/5a/Composite_UML_class_diagram_%28fixed%29.svg/800px-Composite_UML_class_diagram_%28fixed%29.svg.png) how would I wrap it up around with a builder pattern so that client code for creating Composite elements would be simpler and/or more suitable to some form of scripting? – Nebojša May 03 '12 at 20:30
  • BodyPart is the component and Monkey is a composite. This example is flat but if you did a tree, like finger on a hand on an arm then there would be leaves. – eabraham May 03 '12 at 21:13
  • Well, that's what I had in my head prior to asking and what ultimately made me ask the question. While this would work, it appears to be only complicating the client code (or limiting its flexibility) and there is the question whether I would need to make composition of builders to make the whole thing flexible, e.g a builder to make an arm out of smaller body parts, builder to make a leg, and then a builder that will rely on those lower level builders to make entire animal? So I think this would only cause an explosion of classes to keep the whole thing somewhat flexible. – Nebojša May 04 '12 at 08:47
  • A builder increases your number of classes but simplifies complex class creation. – eabraham May 04 '12 at 13:57