Kompositmønster - Composite pattern
I software engineering er det sammensatte mønster et opdelende designmønster . Det sammensatte mønster beskriver en gruppe objekter, der behandles på samme måde som en enkelt forekomst af den samme objekttype. Hensigten med en sammensat er at "komponere" objekter i træstrukturer for at repræsentere delhele hierarkier. Implementering af det sammensatte mønster lader klienter behandle individuelle objekter og sammensætninger ensartet.
Oversigt
Det sammensatte designmønster er et af de tre velkendte GoF-designmønstre, der beskriver, hvordan man løser tilbagevendende designproblemer til at designe fleksibel og genanvendelig objektorienteret software, det vil sige objekter, der er lettere at implementere, ændre, teste og genbruge.
Hvilke problemer kan det sammensatte designmønster løse?
- Et del-hele hierarki bør repræsenteres, så klienter kan behandle dele og hele objekter ensartet.
- Et del-hele hierarki bør repræsenteres som træstruktur.
Ved definition af (1) Part
objekter og (2) Whole
objekter, der fungerer som containere til Part
objekter, skal klienter behandle dem separat, hvilket komplicerer klientkode.
Hvilken løsning beskriver det sammensatte designmønster?
- Definer en samlet
Component
grænseflade for både del (Leaf
) objekter og hele (Composite
) objekter. - Individuelle
Leaf
objekter implementererComponent
grænsefladen direkte, ogComposite
objekter videresender anmodninger til deres underordnede komponenter.
Dette gør det muligt for klienter at arbejde gennem Component
grænsefladen for at behandle Leaf
og Composite
objekter ensartet:
Leaf
objekter udfører en anmodning direkte, og Composite
objekter videresender anmodningen til deres underordnede komponenter rekursivt nedad i træstrukturen. Dette gør klientklasser lettere at implementere, ændre, teste og genbruge.
Se også UML -klassen og objektdiagrammet herunder.
Motivering
Når man beskæftiger sig med træstrukturerede data, er programmører ofte nødt til at skelne mellem en bladknude og en gren. Dette gør koden mere kompleks og derfor mere tilbøjelig til fejl. Løsningen er en grænseflade, der gør det muligt at behandle komplekse og primitive objekter ensartet. I objektorienteret programmering er en komposit et objekt designet som en sammensætning af et eller flere lignende objekter, der alle udviser lignende funktionalitet. Dette er kendt som et " har-et " forhold mellem objekter. Nøglebegrebet er, at du kan manipulere en enkelt forekomst af objektet, ligesom du ville manipulere en gruppe af dem. De operationer, du kan udføre på alle de sammensatte objekter, har ofte et mindst fællesnævnerforhold . For eksempel, hvis du definerer et system til at skildre grupperede former på en skærm, ville det være nyttigt at definere størrelsen på en gruppe af former for at have den samme effekt (i en vis forstand) som at ændre størrelsen på en enkelt form.
Hvornår skal man bruge
Composite bør bruges, når klienter ignorerer forskellen mellem sammensætninger af objekter og individuelle objekter. Hvis programmører finder ud af, at de bruger flere objekter på samme måde og ofte har næsten identisk kode til at håndtere hver af dem, så er komposit et godt valg; det er mindre komplekst i denne situation at behandle primitiver og kompositter som homogene.
Struktur
UML klasse og objektdiagram
I den ovennævnte UML klasse diagram , det Client
betyder klasse ikke henvise til Leaf
og Composite
klasser direkte (separat). I stedet Client
henviser den til den fælles Component
grænseflade og kan behandles Leaf
og Composite
ensartet.
Den Leaf
klasse har ingen børn og redskaber den Component
grænseflade direkte.
Den Composite
klasse opretholder en beholder med underordnede
Component
objekter ( children
) og videresender anmodninger til disse children
( for each child in children: child.operation()
).
Objektsamarbejdsdiagrammet viser interaktioner i løbetid: I dette eksempel Client
sender objektet en anmodning til Composite
objektet på øverste niveau (af typen Component
) i træstrukturen. Anmodningen videresendes til (udføres på) alle underordnede Component
objekter ( Leaf
og Composite
objekter) nedad i træstrukturen.
- Definere børnerelaterede operationer
Der er to designvarianter til at definere og implementere børnerelaterede operationer som tilføjelse/fjernelse af en underordnet komponent til/fra containeren ( add(child)/remove(child)
) og adgang til en underordnet komponent ( getChild()
):
-
Design for ensartethed: Børnerelaterede operationer er defineret i
Component
grænsefladen. Dette gør det muligt for klienter at behandleLeaf
ogComposite
genstande ensartet. Men typesikkerhed går tabt, fordi klienter kan udføre børnerelaterede operationer påLeaf
objekter. -
Design til typesikkerhed: Børnerelaterede operationer defineres kun i
Composite
klassen. Klienter skal behandleLeaf
ogComposite
genstande anderledes. Men typesikkerhed opnås, fordi klienter ikke kan udføre børnelaterede operationer påLeaf
objekter.
Det sammensatte designmønster understreger ensartethed over typesikkerhed .
UML klassediagram
- Komponent
- er abstraktionen for alle komponenter, herunder sammensatte
- erklærer grænsefladen for objekter i sammensætningen
- (valgfrit) definerer en grænseflade til adgang til en komponents forælder i den rekursive struktur og implementerer den, hvis det er passende
- Blad
- repræsenterer bladobjekter i sammensætningen
- implementerer alle komponentmetoder
- Sammensatte
- repræsenterer en sammensat komponent (komponent der får børn)
- implementerer metoder til manipulation af børn
- implementerer alle komponentmetoder, generelt ved at delegere dem til sine børn
Variation
Som det er beskrevet i Design Patterns , involverer mønsteret også at inkludere børnemanipuleringsmetoder i hovedkomponentgrænsefladen, ikke kun den sammensatte underklasse. Nyere beskrivelser udelader undertiden disse metoder.
Eksempel
Følgende eksempel, skrevet i Java , implementerer en grafisk klasse, som enten kan være en ellipse eller en sammensætning af flere grafik. Hver grafik kan udskrives. I Backus-Naur-form ,
Graphic ::= ellipse | GraphicList GraphicList ::= empty | Graphic GraphicList
Det kan udvides til at implementere flere andre former (rektangel osv.) Og metoder ( oversætte osv.).
Java
import java.util.List;
import java.util.ArrayList;
/** "Component" */
interface Graphic {
//Prints the graphic.
public void print();
}
/** "Composite" */
class CompositeGraphic implements Graphic {
//Collection of child graphics.
private final List<Graphic> childGraphics = new ArrayList<>();
//Adds the graphic to the composition.
public void add(Graphic graphic) {
childGraphics.add(graphic);
}
//Prints the graphic.
@Override
public void print() {
for (Graphic graphic : childGraphics) {
graphic.print(); //Delegation
}
}
}
/** "Leaf" */
class Ellipse implements Graphic {
//Prints the graphic.
@Override
public void print() {
System.out.println("Ellipse");
}
}
/** Client */
class CompositeDemo {
public static void main(String[] args) {
//Initialize four ellipses
Ellipse ellipse1 = new Ellipse();
Ellipse ellipse2 = new Ellipse();
Ellipse ellipse3 = new Ellipse();
Ellipse ellipse4 = new Ellipse();
//Creates two composites containing the ellipses
CompositeGraphic compositGraphic2 = new CompositeGraphic();
compositGraphic2.add(ellipse1);
compositGraphic2.add(ellipse2);
compositGraphic2.add(ellipse3);
CompositeGraphic compositGraphic3 = new CompositeGraphic();
compositGraphic3.add(ellipse4);
//Create another graphics that contains two graphics
CompositeGraphic compositGraphic = new CompositeGraphic();
compositGraphic.add(compositGraphic2);
compositGraphic.add(compositGraphic3);
//Prints the complete graphic (Four times the string "Ellipse").
compositGraphic.print();
}
}
Se også
Referencer
eksterne links
- Implementeret sammensat mønster i Java
- Sammensat mønsterbeskrivelse fra Portland Pattern Repository
- Sammensat mønster i UML og i LePUS3, et formelt modelleringssprog
- Klasse :: Delegation på CPAN
- "Afslutningen på arv: Automatisk driftstid-grænsefladebygning til aggregerede objekter" af Paul Baranowski
- PerfectJPattern Open Source Project , Giver komponentiseret implementering af det sammensatte mønster i Java
- [1] En vedvarende Java-baseret implementering
- Sammensat designmønster