2012-05-03 19 views
5

Powiedzmy, że mam Composite skonfigurować w następujący sposób:W jaki sposób powinienem zbliżyć się do zawijania wzoru złożonego do wzorca Konstruktora?

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 
} 

Teraz, jak pójdę o owijając tę ​​Composite się do Builder wzór, tak, że można uprościć kod klienta poprzez umożliwienie mu nie dbać (lub nie obchodziło) o zawiłościach łączenia dzieci z ich Composite?

Odpowiedz

2

Oto przykład budowniczego, który składa się z zwierzęcego kompozytu różnych części zwierzęcych. Powinieneś być w stanie zmodyfikować go dla konkretnej aplikacji.

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; 
     } 
    } 
} 
+0

Dzięki za szybką odpowiedź, ale hows kompozyt Animal tutaj? Może powinienem przeformułować pytanie: Posiadanie struktury podobnej do [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) w jaki sposób zawinąłbym go za pomocą wzorca budowania, aby kod klienta do tworzenia elementów złożonych był prostszy i/lub bardziej odpowiedni do jakiejś formy skryptowania? –

+0

BodyPart jest składnikiem, a Monkey jest kompozytem. Ten przykład jest płaski, ale jeśli zrobiłbyś drzewo, jak palec na ręce na ramieniu, wtedy byłyby liście. – eabraham

+0

Cóż, to było to, co miałem przed sobą w głowie i co ostatecznie sprawiło, że zadałem to pytanie. Chociaż to zadziałałoby, wydaje się, że jedynie komplikuje kod klienta (lub ogranicza jego elastyczność) i pojawia się pytanie, czy powinienem stworzyć kompozycję konstruktorów, aby wszystko było elastyczne, np. Konstruktor, który ma rękę na ramieniu. mniejsze części ciała, budowniczy, który wykona nogę, a potem budowniczy, który będzie polegał na budowniczych niższego poziomu, by stworzyć całe zwierzę? Sądzę więc, że spowodowałoby to tylko eksplozję zajęć, aby utrzymać całą elastyczność. –

0

W swoim konstruktorze dodaj metody "startComposite" i "endComposite". Te metody przesuwają kompozyt na stos i usuwają kompozyt ze stosu. Wiadomości do dodania elementów zawsze dodają do stosu.

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

Jeśli metody builder zawsze powrócić budowniczy, można wyeliminować powtórzenia odbiornika:

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

Hmm, to może być to, czego szukam. Postaram się go rozwiązać w ciągu dnia, aby zobaczyć, jak się okazuje. Dziękuję za Twój czas. –