Összetétel programtervezési minta

A Wikipédiából, a szabad enciklopédiából

A számítógépes programozásban az összetétel programtervezési minta vagy összetétel tervezési minta egy strukturális programtervezési minta. Az összetétel minta az írja le, hogy az objektumok egy csoportját ugyanúgy kell kezelni, mint egy adott objektum példányait külön-külön. Az összetétel itt arra utal, hogy fa struktúrába szervezzünk objektumokat így reprezentálva a rész-egész hierarchiákat. Az összetétel minta lehetővé teszi, hogy a kliensek az önálló objektumokat és összetételeket egységes módon kezeljék.[1]

Motiváció[szerkesztés]

Amikor fa struktúrájú adatokkal foglalkozunk, a fejlesztőnek gyakran különbséget kell tudni tennie a levél elemeket az egyéb csomópontoktól. Ez a kódot még komplexebbé és hibára hajlamossá teszi. A megoldás egy interfész, amely lehetővé teszi a komplex és primitív objektumok egységes kezelését. Az objektumorientált programozásban az összetétel egy objektum tervezési mód, hasonló objektumok 1 vagy több kapcsolata, mindegyik hasonló funkcionalitással ellátva. Ezt úgy hívják, hogy "has-a" kapcsolat objektumok között.[2] A kulcs fogalom az, hogy hogyan lehet manipulálni az objektum egy példányát ugyanúgy, mintha az objektum egy egész csoportját manipulálnánk. Azoknak a műveleteknek, melyeket végre lehet hajtani az összes összetett objektumon gyakran van egy legkisebb közös nevező kapcsolata. Például ha a képernyőn egy rendszert definiálunk csoportosított alakzatok képeihez, hasznos lenne, ha definiálnánk átméretezését az alakzatok egy csoportjára, úgy hogy ugyanaz a hatásuk (bizonyos értelemben) legyen mintha csak egy alakzatot kellett volna átméretezni.

Használata[szerkesztés]

Az összetételt akkor célszerű használni, ha a kliensek figyelmen kívül hagyják a különbséget az objektumok összetétele és az önálló objektumok között.[1] Ha fejlesztők úgy találják, hogy több objektumot akarnak azonos módon használni és gyakran van majdnem azonos kódjuk az egyes elemek kezelésére, akkor az összetétel egy jó választás; kevésbé komplex ebben az esetben kezelni az egyszerű és összetett objektumokat homogén módon.

Struktúra[szerkesztés]

Összetétel tervezési minta UML-ben.
Komponens
  • absztrakció az összes összetevőhöz, beleértve az összetettet is
  • az objektumok számára meghatározza az interfészt az összetételben
  • (nem kötelező) meghatározza az interfészt egy komponens szülőjének eléréséhez a rekurzív struktúrában, és megvalósítja azt, amennyiben szükséges
Levél elem
  • reprezentálja a levél objektumokat az összetételben
  • megvalósítja az összes komponens metódust
Összetétel
  • reprezentál egy összetett komponenst (gyerekekkel rendelkező komponens)
  • megvalósítja a gyerekek kezeléséhez szükséges metódusokat
  • megvalósítja az összes komponens metódust, általában a gyerekekhez való delegálással
Összetétel minta LePUS3-ban.

Variációk[szerkesztés]

Mint ahogy azt leírtuk a tervezési mintákban a minta szintén magába foglalja a gyerek kezeléséhez szükséges metódusokat a fő komponens interfészében, nem csak az összetétel alosztályaiban. Újabb leírásokban néha kihagyják ezeket a metódusokat.[3]

Példák[szerkesztés]

A következő példa Java nyelven íródott, amely egy grafikus osztályt implementál, amely lehet egy ellipszis vagy a más grafikus elemek összetétele. Minden grafika nyomtatható. A Backus-Naur-formával:

       Graphic = ellipse | GraphicList
       GraphicList = empty | Graphic GraphicList

Ki lehet terjeszteni, hogy számos más alakot (négyzet stb.) ill. metódust (forgatást stb.) implementáljon.

Java[szerkesztés]

/** "Component" */
interface Graphic {

    //Prints the graphic.
    public void print();
}

/** "Composite" */
import java.util.List;
import java.util.ArrayList;
class CompositeGraphic implements Graphic {

    //Collection of child graphics.
    private List<Graphic> childGraphics = new ArrayList<Graphic>();

    //Prints the graphic.
    public void print() {
        for (Graphic graphic : childGraphics) {
            graphic.print();
        }
    }

    //Adds the graphic to the composition.
    public void add(Graphic graphic) {
        childGraphics.add(graphic);
    }

    //Removes the graphic from the composition.
    public void remove(Graphic graphic) {
        childGraphics.remove(graphic);
    }
}

/** "Leaf" */
class Ellipse implements Graphic {

    //Prints the graphic.
    public void print() {
        System.out.println("Ellipse");
    }
}

/** Client */
public class Program {

    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();

        //Initialize three composite graphics
        CompositeGraphic graphic = new CompositeGraphic();
        CompositeGraphic graphic1 = new CompositeGraphic();
        CompositeGraphic graphic2 = new CompositeGraphic();

        //Composes the graphics
        graphic1.add(ellipse1);
        graphic1.add(ellipse2);
        graphic1.add(ellipse3);

        graphic2.add(ellipse4);

        graphic.add(graphic1);
        graphic.add(graphic2);

        //Prints the complete graphic (four times the string "Ellipse").
        graphic.print();
    }
}

C#[szerkesztés]

A következő grafikai példa C#-en íródott.

namespace CompositePattern
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    //Client
    class Program
    {
        static void Main(string[] args)
        {
            // initialize variables
            var compositeGraphic = new CompositeGraphic();
            var compositeGraphic1 = new CompositeGraphic();
            var compositeGraphic2 = new CompositeGraphic();

            //Add 1 Graphic to compositeGraphic1
            compositeGraphic1.Add(new Ellipse());

            //Add 2 Graphic to compositeGraphic2
            compositeGraphic2.AddRange(new Ellipse(), 
                new Ellipse());

            /*Add 1 Graphic, compositeGraphic1, and 
              compositeGraphic2 to compositeGraphic */
            compositeGraphic.AddRange(new Ellipse(), 
                compositeGraphic1, 
                compositeGraphic2);

            /*Prints the complete graphic 
            (four times the string "Ellipse").*/
            compositeGraphic.Print();
            Console.ReadLine();
        }
    }
    //Component
    public interface IGraphic
    {
        void Print();
    }
    //Leaf
    public class Ellipse : IGraphic
    {
        //Prints the graphic
        public void Print()
        {
            Console.WriteLine("Ellipse");
        }
    }
    //Composite
    public class CompositeGraphic : IGraphic
    {
        //Collection of Graphics.
        private readonly List<IGraphic> graphics;

        //Constructor 
        public CompositeGraphic()
        {
            //initialize generic Collection(Composition)
            graphics = new List<IGraphic>();
        }
        //Adds the graphic to the composition
        public void Add(IGraphic graphic)
        {
            graphics.Add(graphic);
        }
        //Adds multiple graphics to the composition
        public void AddRange(params IGraphic[] graphic)
        {
            graphics.AddRange(graphic);
        }
        //Removes the graphic from the composition
        public void Delete(IGraphic graphic)
        {
            graphics.Remove(graphic);
        }
        //Prints the graphic.
        public void Print()
        {
            foreach (var childGraphic in graphics)
            {
                childGraphic.Print();
            }
        }
    }
}

Egy egyszerű példa[szerkesztés]

    //IVSR: Composite example
    /// Treats elements as composition of one or more elements, so that components 
    /// can be separated between one another
    public interface IComposite
    {
        void CompositeMethod();
    }

    public class LeafComposite :IComposite 
    {

        #region IComposite Members

        public void CompositeMethod()
        {
            //To Do something
        }

        #endregion
    }

    /// Elements from IComposite can be separated from others 
    public class NormalComposite : IComposite
    {

        #region IComposite Members

        public void CompositeMethod()
        {
            //To Do Something
        }

        #endregion

        public void DoSomethingMore()
        {
            //Do Something more .
        }
    }

Kapcsolódó szócikkek[szerkesztés]

További információk[szerkesztés]

Az angol Wikikönyvekben
további információk találhatók

Jegyzetek[szerkesztés]

  1. a b Gamma, Erich. Design Patterns: Elements of Reusable Object-Oriented Software. Addison-Wesley, 395. o. (1995). ISBN 0-201-63361-2 
  2. Scott Walters. Perl Design Patterns Book (2004). Hozzáférés ideje: 2015. február 17. 
  3. Geary, David: A look at the Composite design pattern, 2002. szeptember 13. [2013. október 31-i dátummal az eredetiből archiválva]. (Hozzáférés: 2015. február 17.)

Fordítás[szerkesztés]

Ez a szócikk részben vagy egészben a Composite pattern című angol Wikipédia-szócikk ezen változatának fordításán alapul. Az eredeti cikk szerkesztőit annak laptörténete sorolja fel. Ez a jelzés csupán a megfogalmazás eredetét és a szerzői jogokat jelzi, nem szolgál a cikkben szereplő információk forrásmegjelöléseként.