Sammansatt mönster

Inom mjukvaruteknik är det sammansatta mönstret ett partitioneringsmönster . Det sammansatta mönstret beskriver en grupp av objekt som behandlas på samma sätt som en enda instans av samma typ av objekt. Avsikten med en sammansatt är att "komponera" objekt till trädstrukturer för att representera del-hela hierarkier. Genom att implementera det sammansatta mönstret kan kunderna behandla enskilda objekt och kompositioner enhetligt.

Översikt

Det sammansatta designmönstret är ett av de tjugotre välkända GoF-designmönstren som beskriver hur man löser återkommande designproblem för att designa flexibel och återanvändbar objektorienterad programvara, det vill säga objekt som är lättare att implementera, ändra, testa och återanvändning.

Vilka problem kan det sammansatta designmönstret lösa?

  • En del-hel hierarki bör representeras så att klienter kan behandla delar och hela objekt enhetligt.
  • En del-hel hierarki bör representeras som trädstruktur.

När man definierar (1) Delobjekt och (2) Hela objekt som fungerar som behållare för Delobjekt måste klienter behandla dem separat, vilket komplicerar klientkoden.

Vilken lösning beskriver Composite-designmönstret?

  • Definiera ett enhetligt komponentgränssnitt för både del- ( Leaf ) objekt och hela ( Composite ) objekt.
  • Individuella Leaf -objekt implementerar Component- gränssnittet direkt, och Composite -objekt vidarebefordrar förfrågningar till sina underordnade komponenter.

Detta gör det möjligt för klienter att arbeta genom komponentgränssnittet för att behandla Leaf- och Composite -objekt enhetligt: ​​Leaf -objekt utför en begäran direkt, och Composite -objekt vidarebefordrar begäran till sina underordnade komponenter rekursivt nedåt i trädstrukturen. Detta gör klientklasser lättare att implementera, ändra, testa och återanvända.

Se även UML klass- och objektdiagram nedan.

Motivering

När de hanterar trädstrukturerade data måste programmerare ofta skilja mellan en lövnod och en gren. Detta gör koden mer komplex och därför mer felbenägen. Lösningen är ett gränssnitt som gör det möjligt att behandla komplexa och primitiva objekt enhetligt. I objektorienterad programmering är en komposit ett objekt utformat som en sammansättning av ett eller flera liknande objekt, som alla uppvisar liknande funktionalitet. Detta är känt som ett " har-ett "-förhållande mellan objekt. Nyckelkonceptet är att du kan manipulera en enda instans av objektet precis som du skulle manipulera en grupp av dem. De operationer du kan utföra på alla sammansatta objekt har ofta ett minsta gemensamma nämnarförhållande . Till exempel, om man definierar ett system för att porträttera grupperade former på en skärm, skulle det vara användbart att definiera storleksändring av en grupp av former för att ha samma effekt (i någon mening) som att ändra storlek på en enskild form.

När ska användas

Komposit bör användas när klienter ignorerar skillnaden mellan sammansättningar av objekt och enskilda objekt. Om programmerare upptäcker att de använder flera objekt på samma sätt och ofta har nästan identisk kod för att hantera vart och ett av dem, så är komposit ett bra val; det är mindre komplicerat i denna situation att behandla primitiver och kompositer som homogena.

Strukturera

UML klass och objektdiagram

Ett exempel på UML-klass- och objektdiagram för det sammansatta designmönstret.



I ovanstående UML- klassdiagram hänvisar klientklassen inte till Leaf- och Composite -klasserna direkt ( separat). Istället hänvisar klienten till det gemensamma komponentgränssnittet och kan behandla Leaf och Composite enhetligt. Leaf - klassen har inga barn och implementerar Component -gränssnittet direkt. Klassen Composite upprätthåller en behållare med underordnade komponentobjekt ( barn ) och vidarebefordrar förfrågningar till dessa underordnade ( för varje barn i barn: child.operation() ).

Objektsamarbetsdiagrammet visar körtidsinteraktionerna: I det här exemplet skickar klientobjektet en begäran till det sammansatta objektet på toppnivån ( av typen Component ) i trädstrukturen. Begäran vidarebefordras till (utförs på) alla underordnade komponentobjekt ( blad och sammansatta objekt) nedåt i trädstrukturen.

Definiera barnrelaterade operationer
Definiera barnrelaterade operationer i det sammansatta designmönstret.

Det finns två designvarianter för att definiera och implementera barnrelaterade operationer som att lägga till/ta bort en underordnad komponent till/från behållaren ( add(child)/remove(child)) och åtkomst till en underordnad komponent ( getChild() ):

  • Design för enhetlighet: Barnrelaterade operationer definieras i komponentgränssnittet . Detta gör det möjligt för kunder att behandla blad och kompositobjekt enhetligt. Men typsäkerheten går förlorad eftersom klienter kan utföra barnrelaterade operationer på Leaf- objekt.
  • Design för typsäkerhet: Barnrelaterade operationer definieras endast i Composite -klassen. Kunder måste behandla Leaf- och Composite -objekt olika. Men typsäkerhet uppnås eftersom klienter inte kan utföra barnrelaterade operationer på Leaf- objekt.

Designmönstret i komposit betonar enhetlighet framför typsäkerhet .

UML klassdiagram

Kompositmönster i UML .
Komponent
  • är abstraktionen för alla komponenter, inklusive sammansatta
  • deklarerar gränssnittet för objekt i kompositionen
  • (valfritt) definierar ett gränssnitt för åtkomst till en komponents överordnade i den rekursiva strukturen, och implementerar det om det är lämpligt
Blad
  • representerar lövobjekt i kompositionen
  • implementerar alla komponentmetoder
Sammansatt
  • representerar en sammansatt komponent (komponent som har barn)
  • implementerar metoder för att manipulera barn
  • implementerar alla komponentmetoder, vanligtvis genom att delegera dem till sina barn
Kompositmönster i LePUS3.

Variation

Som det beskrivs i Design Patterns innefattar mönstret också att inkludera barnmanipuleringsmetoderna i huvudkomponentgränssnittet, inte bara Composite-underklassen. Nyare beskrivningar utelämnar ibland dessa metoder.

Exempel

Följande exempel, skrivet i Java , implementerar en grafikklass, som kan vara antingen en ellips eller en sammansättning av flera grafik. Varje grafik kan skrivas ut. I Backus-Naur form ,

Grafik ::= ellips | GraphicList GraphicList ::= tom | Grafisk grafisk lista

Det kan utökas till att implementera flera andra former (rektangel, etc.) och metoder ( translate , etc.).

Java

 
 


  
    
      



    
    
          

    
        
        
    
    
    
    
       
             
              
        
    



    
    
    
       
        
    



  
         
        
            
            
            
            

        
            
        
        
        
        
            
        
        
        
            
        
        

        
        
    
 importera  java.util.List  ;  importera  java.util.ArrayList  ;  /** "Komponent" */  interface  Graphic  {  //Skriver ut grafiken.  public  void  print  ();  }  /** "Composite" */  class  CompositeGraphic  implementerar  Graphic  {  //Samling av underordnad grafik.  private  final  List  <  Graphic  >  childGraphics  =  new  ArrayList  <>  ();  //Lägger till grafiken till kompositionen.  public  void  add  (  Graphic  graphic  )  {  childGraphics  .  add  (  grafik  );  }  //Skriver ut grafiken.  @Override  public  void  print  ()  {  for  (  Graphic  graphic  :  childGraphics  )  {  graphic  .  print  ();  //Delegation  }  }  }  /** "Löv" */  class  Ellipse  implements  Graphic  {  //Skriver ut grafiken.  @Override  public  void  print  ()  {  System  .  ut  .  println  (  "Ellips"  );  } }  /  ** Client */  class  CompositeDemo  {  public  static  void  main  (  String  []  args  )  {  //Initialisera fyra ellipser  Ellipse  ellips1  =  new  Ellipse  ();  Ellips  ellips2  =  ny  Ellips  ();  Ellips  ellips3  =  ny  Ellips  ();  Ellips  ellips4  =  ny  Ellips  ();  //Skapar två kompositer som innehåller ellipserna  CompositeGraphic  compositGraphic2  =  new  CompositeGraphic (  );  compositGraphic2  .  add  (  ellips1  );  compositGraphic2  .  add  (  ellips2  );  compositGraphic2  .  add  (  ellips3  );  CompositeGraphic  compositGraphic3  =  ny  CompositeGraphic  ();  compositGraphic3  .  add  (  ellips4  );  //Skapa ytterligare en grafik som innehåller två grafik  CompositeGraphic  compositGraphic  =  new  CompositeGraphic  ();  compositGraphic  .  add  (  compositGraphic2  );  compositGraphic  .  add  (  compositGraphic3  );  //Skriver ut hela grafiken (fyra gånger strängen "Ellipse").  compositGraphic  .  print  ();  }  } 

Se även

externa länkar