Компоновщик (шаблон проектирования)

Материал из Seo Wiki - Поисковая Оптимизация и Программирование
Перейти к навигацииПерейти к поиску

Компоновщик (англ. Composite pattern) — шаблон проектирования, объединяет объекты в древовидную структуру для представления иерархии от частного к целому. Компоновщик позволяет клиентам обращаться к отдельным объектам и к группам объектов одинаково.

Цель

Паттерн определяет иерархию классов, которые могут состоять из примитивных и сложных объектов, упрощает архитектуру клиента, делает процесс добавления новых видов объекта более простым.

Описание

UML-диаграмма шаблона:

Файл:Composite.gif

Примеры реализации

Пример на 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 List<Graphic> mChildGraphics = new ArrayList<Graphic>();

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

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

    //Removes the graphic from the composition.
    public void remove(Graphic graphic) {
        mChildGraphics.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#

  class MainApp
  {
 
    static void Main()
    {
 
      // Create a tree structure
      Component root = new Composite("root");
 
      root.Add(new Leaf("Leaf A"));
      root.Add(new Leaf("Leaf B"));
 
      Component comp = new Composite("Composite X");
 
      comp.Add(new Leaf("Leaf XA"));
      comp.Add(new Leaf("Leaf XB"));
      root.Add(comp);
      root.Add(new Leaf("Leaf C"));
 
      // Add and remove a leaf
      Leaf leaf = new Leaf("Leaf D");
      root.Add(leaf);
      root.Remove(leaf);
 
      // Recursively display tree
      root.Display(1);
 
      // Wait for user
      Console.Read();
 
    }
  }
 
  /// <summary>
  /// Component - компонент
  /// </summary>
  /// <li>
  /// <lu>объявляет интерфейс для компонуемых объектов;</lu>
  /// <lu>предоставляет подходящую реализацию операций по умолчанию,
  /// общую для всех классов;</lu>
  /// <lu>объявляет интерфейс для доступа к потомкам и управлению ими;</lu>
  /// <lu>определяет интерфейс доступа к родителю компонента в рекурсивной структуре
  /// и при необходимости реализует его. Описанная возможность необязательна;</lu>
  /// </li>
  abstract class Component
  {
    protected string name;
 
    // Constructor
    public Component(string name)
    {
      this.name = name;
    }
 
    public abstract void Add(Component c);
    public abstract void Remove(Component c);
    public abstract void Display(int depth);
  }
 
  /// <summary>
  /// Composite - составной объект
  /// </summary>
  /// <li>
  /// <lu>определяет поведеление компонентов, у которых есть потомки;</lu>
  /// <lu>хранит компоненты-потомоки;</lu>
  /// <lu>реализует относящиеся к управлению потомками операции и интерфейсе
  /// класса <see cref="Component"/></lu>
  /// </li>
  class Composite : Component
  {
    private ArrayList children = new ArrayList();
 
    // Constructor
    public Composite(string name) : base(name)
    {  
    }
 
    public override void Add(Component component)
    {
      children.Add(component);
    }
 
    public override void Remove(Component component)
    {
      children.Remove(component);
    }
 
    public override void Display(int depth)
    {
      Console.WriteLine(new String('-', depth) + name);
 
      // Recursively display child nodes
      foreach (Component component in children)
      {
        component.Display(depth + 2);
      }
    }
  }
 
  /// <summary>
  /// Leaf - лист
  /// </summary>
  /// <remarks>
  /// <li>
  /// <lu>представляет листовой узел композиции и не имеет потомков;</lu>
  /// <lu>определяет поведение примитивных объектов в композиции;</lu>
  /// </li>
  /// </remarks>
  class Leaf : Component
  {
 
    // Constructor
    public Leaf(string name) : base(name)
    {  
    }
 
    public override void Add(Component c)
    {
      Console.WriteLine("Cannot add to a leaf");
    }
 
    public override void Remove(Component c)
    {
      Console.WriteLine("Cannot remove from a leaf");
    }
 
    public override void Display(int depth)
    {
      Console.WriteLine(new String('-', depth) + name);
    }
  }

Пример на C++

#include <iostream>
#include <list>
#include <algorithm>
#include <boost/shared_ptr.hpp>
#include <boost/foreach.hpp>

struct IText{

	typedef boost::shared_ptr<IText> SPtr;

	virtual void draw() = 0;

	virtual void add(const SPtr&) {
		throw std::runtime_error("IText: Can't add to a leaf");
	}

	virtual void remove(const SPtr&){
		throw std::runtime_error("IText: Can't remove from a leaf");
	}
};

struct CompositeText: public IText{
	
	void add(const SPtr& sptr){
		_children.push_back(sptr);
	}

	void remove(const SPtr& sptr){
		_children.remove(sptr);
	}

	void replace(const SPtr& oldValue, const SPtr& newValue){
		std::replace(_children.begin(), _children.end(), oldValue, newValue);
	}

	virtual void draw(){
		BOOST_FOREACH(SPtr& sptr, _children){
			sptr->draw();
		}
	}

private:
	std::list<SPtr> _children;
};

struct Letter: public IText{

	Letter(char c):_c(c) {}

	virtual void draw(){
		std::cout<<_c;
	}

private:
	char _c;
};


int main(){
	
	CompositeText sentence;
	
	IText::SPtr space(new Letter(' '));
	IText::SPtr excl(new Letter('!'));
	IText::SPtr comma(new Letter(','));
	IText::SPtr newline(new Letter('\n'));

	IText::SPtr hello(new CompositeText);
	hello->add(IText::SPtr(new Letter('H')));
	hello->add(IText::SPtr(new Letter('e')));
	hello->add(IText::SPtr(new Letter('l')));
	hello->add(IText::SPtr(new Letter('l')));
	hello->add(IText::SPtr(new Letter('o')));

	IText::SPtr world(new CompositeText);
	world->add(IText::SPtr(new Letter('W')));
	world->add(IText::SPtr(new Letter('o')));
	world->add(IText::SPtr(new Letter('r')));
	world->add(IText::SPtr(new Letter('l')));
	world->add(IText::SPtr(new Letter('d')));

	sentence.add(hello);
	sentence.add(comma);
	sentence.add(space);
	sentence.add(world);
	sentence.add(excl);
	sentence.add(newline);

	sentence.draw();  // ptrints "Hello, World!\n"

	IText::SPtr hi(new CompositeText);
	hi->add(IText::SPtr(new Letter('H')));
	hi->add(IText::SPtr(new Letter('i')));

	sentence.replace(hello, hi);
	sentence.draw();  // ptrints "Hi, World!\n"

	sentence.remove(world);
	sentence.remove(space);
	sentence.remove(comma);
	sentence.draw();  // ptrints "Hi!\n"

	return 0;
}



структурные шаблоны проектирования

адаптер | мост | компоновщик | декоратор | фасад | заместитель | приспособленец | Выделение частного класса данных

bg:Композиция (шаблон) cs:Composite de:Kompositum (Entwurfsmuster) en:Composite pattern es:Composite (patrón de diseño) fr:Objet composite it:Composite ja:Composite パターン ko:Composite 패턴 pl:Kompozyt (wzorzec projektowy) pt:Composite th:คอมโพสิตแพตเทิร์น vi:Composite pattern

Если вам нравится SbUP.com Сайт, вы можете поддержать его - BTC: bc1qppjcl3c2cyjazy6lepmrv3fh6ke9mxs7zpfky0 , TRC20 и ещё....