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

Материал из 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

Личные инструменты

Served in 0.518 secs.