Семя – орган полового размножения и расселения растений: наружи у семян имеется плотный покров – кожура...
Археология об основании Рима: Новые раскопки проясняют и такой острый дискуссионный вопрос, как дата самого возникновения Рима...
Топ:
Отражение на счетах бухгалтерского учета процесса приобретения: Процесс заготовления представляет систему экономических событий, включающих приобретение организацией у поставщиков сырья...
Особенности труда и отдыха в условиях низких температур: К работам при низких температурах на открытом воздухе и в не отапливаемых помещениях допускаются лица не моложе 18 лет, прошедшие...
Определение места расположения распределительного центра: Фирма реализует продукцию на рынках сбыта и имеет постоянных поставщиков в разных регионах. Увеличение объема продаж...
Интересное:
Как мы говорим и как мы слушаем: общение можно сравнить с огромным зонтиком, под которым скрыто все...
Наиболее распространенные виды рака: Раковая опухоль — это самостоятельное новообразование, которое может возникнуть и от повышенного давления...
Средства для ингаляционного наркоза: Наркоз наступает в результате вдыхания (ингаляции) средств, которое осуществляют или с помощью маски...
Дисциплины:
2019-08-07 | 155 |
5.00
из
|
Заказать работу |
|
|
Компоновщик (англ. Composite pattern) — шаблон проектирования, объединяет объекты в древовидную структуру для представления иерархии от частного к целому. Компоновщик позволяет клиентам обращаться к отдельным объектам и к группам объектов одинаково.
Цель
Паттерн определяет иерархию классов, которые состоят из примитивных и сложных объектов, упрощает архитектуру клиента, делает процесс добавления новых видов объекта более простым.
Описание
Примеры
Пример на 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();
}
}
Декоратор (шаблон проектирования)
Декоратор, Decorator — структурный шаблон проектирования, предназначенный для динамического подключения дополнительного поведения к объекту. Шаблон Декоратор предоставляет гибкую альтернативу практике создания подклассов с целью расширения функциональности.
|
Известен также под менее распространённым названием Обёртка (Wrapper), которое во многом раскрывает суть реализации шаблона.
Основные характеристики
Задача
Объект, который предполагается использовать, выполняет основные функции. Однако может потребоваться добавить к нему некоторую дополнительную функциональность, которая будет выполняться до, после или даже вместо основной функциональности объекта.
Способ решения
Декоратор предусматривает расширение функциональности объекта без определения подклассов.
Участники
Класс ConcreteComponent — класс, в который с помощью шаблона Декоратор добавляется новая функциональность. В некоторых случаях базовая функциональность предоставляется классами, производными от класса ConcreteComponent. В подобных случаях класс ConcreteComponent является уже не конкретным, а абстрактным. Абстрактный класс Component определяет интерфейс для использования всех этих классов.
Следствия
1. Добавляемая функциональность реализуется в небольших объектах. Преимущество состоит в возможности динамически добавлять эту функциональность до или после основной функциональности объекта ConcreteComponent.
2. Позволяет избегать перегрузки функциональными классами на верхних уровнях иерархии
3. Декоратор и его компоненты не являются идентичными
Реализация
Создается абстрактный класс, представляющий как исходный класс, так и новые, добавляемые в класс функции. В классах-декораторах новые функции вызываются в требуемой последовательности — до или после вызова последующего объекта.
При желании остаётся возможность использовать исходный класс (без расширения функциональности), если на его объект сохранилась ссылка.
Замечания и комментарии
Применение шаблона
|
Примеры реализации [показать]
Пример реализации шаблона на C#
using System;
namespace Decorator
{
class MainApp
{
static void Main()
{
// Create ConcreteComponent and two Decorators
ConcreteComponent c = new ConcreteComponent();
ConcreteDecoratorA d1 = new ConcreteDecoratorA();
ConcreteDecoratorB d2 = new ConcreteDecoratorB();
// Link decorators
d1.SetComponent(c);
d2.SetComponent(d1);
d2.Operation();
// Wait for user
Console.Read();
}
}
/// <summary>
/// Component - компонент
/// </summary>
/// <remarks>
/// <li>
/// <lu>определяем интерфейс для объектов, на которые могут быть динамически
/// возложены дополнительные обязанности;</lu>
/// </li>
/// </remarks>
abstract class Component
{
public abstract void Operation();
}
/// <summary>
/// ConcreteComponent - конкретный компонент
/// </summary>
/// <remarks>
/// <li>
/// <lu>определяет объект, на который возлагается дополнительные обязаности</lu>
/// </li>
/// </remarks>
class ConcreteComponent: Component
{
public override void Operation()
{
Console.WriteLine("ConcreteComponent.Operation()");
}
}
/// <summary>
/// Decorator - декоратор
/// </summary>
/// <remarks>
/// <li>
/// <lu>хранит ссылку на объект <see cref="Component"/> и определяет интерфейс,
/// соотведствующий интерфейсу <see cref="Component"/></lu>
/// </li>
/// </remarks>
abstract class Decorator: Component
{
protected Component component;
public void SetComponent(Component component)
{
this.component = component;
}
public override void Operation()
{
if (component!= null)
{
component.Operation();
}
}
}
/// <summary>
/// ConcreteDecorator - конкретный декоратор
/// </summary>
/// <remarks>
/// <li>
/// <lu>возглагает дополнительные обязанности на компонент.</lu>
/// </li>
/// </remarks>
class ConcreteDecoratorA: Decorator
{
private string addedState;
public override void Operation()
{
base.Operation();
addedState = "New State";
Console.WriteLine("ConcreteDecoratorA.Operation()");
}
}
// "ConcreteDecoratorB"
class ConcreteDecoratorB: Decorator
{
public override void Operation()
{
base.Operation();
AddedBehavior();
Console.WriteLine("ConcreteDecoratorB.Operation()");
}
void AddedBehavior()
{
}
}
}
Примеры реализации на JavaScript
Шаблон декоратор в языках с динамической типизацией может быть применен без интерфейсов и традиционного для ООП наследования.
Этот пример скопирован с английской версии статьи. Расчет стоимости кофе:
// ConcreteComponent (класс для последующего декорирования)
function Coffee() {
|
this.cost = function() {
return 1;
};
}
// Decorator A
function Milk(coffee) {
this.cost = function() {
return coffee.cost() + 0.5;
};
}
// Decorator B
function Whip(coffee) {
this.cost = function() {
return coffee.cost() + 0.7;
};
}
// Decorator C
function Sprinkles(coffee) {
this.cost = function() {
return coffee.cost() + 0.2;
};
}
// Можно использовать, например, так:
var coffee = new Milk(new Whip(new Sprinkles(new Coffee())));
alert(coffee.cost());
// Или более наглядно:
var coffee = new Coffee();
coffee = new Sprinkles(coffee);
coffee = new Whip(coffee);
coffee = new Milk(coffee);
alert(coffee.cost());
Реализация имеющегося выше C# примера. В ConcreteComponent добавлена локальная переменная price, которая будет изменяться как в нем самом, так и декораторах. Имена классов (кроме постфиксов "A" и "B") совпадают с именами участников шаблона.
function Component() {
this.operation = function() { };
this.getPrice = function() { };
this.setPrice = function() { };
}
function ConcreteComponent() {
var price = 10;
this.operation = function() {
price += 4;
alert("ConcreteComponent.operation, price: "+ price);
};
this.getPrice = function() {
return price;
};
this.setPrice = function(val) {
price = val;
};
}
ConcreteComponent.prototype = new Component();
ConcreteComponent.prototype.constructor = ConcreteComponent;
function Decorator() {
var component;
this.setComponent = function(val) {
component = val;
};
this.getComponent = function() {
return component;
};
this.operation = function() {
component.operation();
};
this.getPrice = function() {
return component.getPrice();
};
this.setPrice = function(val) {
component.setPrice(val);
};
}
Decorator.prototype = new Component();
Decorator.prototype.constructor = Decorator;
function ConcreteDecoratorA() {
Decorator.call(this);
var operation = this.operation; // ссылка на метод, определенный в Decorator
this.operation = function() {
this.setPrice(this.getPrice() + 3);
alert("ConcreteDecoratorA.operation, price: "+ this.getPrice());
operation();
};
}
function ConcreteDecoratorB() {
var dublicate = this; // ссылка на инстанцирующийся объект (т.к. this может меняться)
Decorator.call(this);
var operation = this.operation; // ссылка на метод, определенный в Decorator
this.operation = function() {
this.setPrice(this.getPrice() + 1);
alert("ConcreteDecoratorB.operation, price: "+ this.getPrice());
addedBehavior();
operation();
};
function addedBehavior() {
dublicate.setPrice(dublicate.getPrice() + 2);
alert("addedBehavior, price: "+ dublicate.getPrice());
}
}
// использование
c = new ConcreteComponent();
d1 = new ConcreteDecoratorA();
d2 = new ConcreteDecoratorB();
alert("изначальная цена: " + c.getPrice()); // 10
d1.setComponent(c);
d2.setComponent(d1);
d2.operation();
alert("цена после преобразования: " + c.getPrice()); // 20
Литература
Э. Гамма, Р. Хелм, Р. Джонсон, Дж. Влиссидес Приемы объектно-ориентированного проектирования. Паттерны проектирования = Design Patterns: Elements of Reusable Object-Oriented Software. — СПб: «Питер», 2007. — С. 366.
|
Алан Шаллоуей, Джеймс Р. Тротт Шаблоны проектирования. Новый подход к объектно-ориентированному анализу и проектированию = Design Patterns Explained: A New Perspective on Object-Oriented Design. — М.: «Вильямс», 2002. — С. 288.
|
|
Таксономические единицы (категории) растений: Каждая система классификации состоит из определённых соподчиненных друг другу...
Автоматическое растормаживание колес: Тормозные устройства колес предназначены для уменьшения длины пробега и улучшения маневрирования ВС при...
Археология об основании Рима: Новые раскопки проясняют и такой острый дискуссионный вопрос, как дата самого возникновения Рима...
Биохимия спиртового брожения: Основу технологии получения пива составляет спиртовое брожение, - при котором сахар превращается...
© cyberpedia.su 2017-2024 - Не является автором материалов. Исключительное право сохранено за автором текста.
Если вы не хотите, чтобы данный материал был у нас на сайте, перейдите по ссылке: Нарушение авторских прав. Мы поможем в написании вашей работы!