Decorator (patrono de designo)

Le patrono Decorator responde al necessitate de appender dynamicamente le functionalitate a un objecto. Isto permitte evitar de crear classes successive qui heredita del prime e incorpora le nove functionalitate, sed, in vice, alteres qui implementa lo e se associa al prime.

 Motivation 
Un exemplo pro poter vider le applicabilitate del patrono decorator poterea esser le sequente:
On dispone de un utensile pro crear interfacies graphic, qui permitte de appender functionalitates como bordos o barras de displaciamento a un qualcunque componente del interfacie. 
Un possibile solution esserea usar le hereditate pro extender le responsabilitates del classe. Si on selectiona iste solution, on facerea un designo inlexibile (static), durante que le cliente non pote controlar quando e como decorar le componente con aquelle proprietate.
Le solution es de encapsular dentro de altere objecto, nominate Decorator, le nove responsabilitates. Le decorator redirige le petitiones al componente e, de plus, pote realisar actiones additional ante e post le redirection. De iste maniera, on pote appender decoratores con qualitates appendite recursivemente.

decorator concrete  

In iste diagramma de classes, on pote vider que le interfacie decorator implementa le interfacie del componente, e redirige tote le methodos al componente visual le qual illo encapsula.
Le subclasses decorator raffina le methodos del componente, per adder responsabilitates.
Anque on pote vider que le cliente non necessita de facer un distinction inter le componentes visual decorate e le componentes sin decoration.
sequentia decorator 

 Applicabilitate 
 Appender responsabilitates a objectos individual de forma dynamic e transparente
 Responsabilitates de un objecto pote esser retirate
 Quando le extension mediante le hereditate non es viabile. 
 Il ha un necessitate de extender le functionalitate de un classe, sed il non ha rationes pro extender lo a transverso del hereditate. 
 Il ha le necessitate de extender dynamicamente le functionalitate de un objecto e forsan quitar le functionalitate extendite.

 Structura 
Decorator generic 

 Participantes 
 Componente
Defini le interfacie pro le objectos qui pote haber responsabilitates appendite.
Componente Concrete
Defini un objecto al qual on pote aggregar responsabilitates additional.
Decorator
Mantene un referentia al componente associate. Implementa le interfacie del superclasse Componente per delegar in le componente associate.
Decorator Concrete
Appende responsabilitates al componente.

 Collaborationes 
Le decorator redirige le petitiones al componente associate.
Optionalmente illo pote realisar cargas additional ante e post rediriger le petition.

 Consequentias 
Plus flexibile que le hereditate. Al utilisar iste patrono, on pote appender e eliminar responsabilitates in tempore de execution. De plus, illo evita le uso del hereditate con multe classes e anque, in alcun casos, le hereditate multiple.
Illo evita le apparition de classes con multe responsabilitates in le classes superior del hierarchia. Iste patrono permitte al programmator de incorporar responsabilitates de modo incremental.
Illo genera grande quantitate de objectos parve. Le uso de decoratores da como resultato systemas formate per multe objectos parve e simile.
Il pote haber problemas con le identitate del objectos. Un decorator se comporta como un copertura transparente, sed ab le puncto de vista del identitate de objectos, istos non es identic, dunque on deberea evitar appoiar se in le identitate quando on usa decoratores.

 Implementation 
Le patrono Decorator solutiona iste problema de un maniera multo plus simple e extensibile.

On crea a partir de Fenestra le subclasse abstracte FenestraDecorator e, per hereditar de illo, BordoDecorator e ButtonDeAdjutaDecorator. FenestraDecorator encapsula le comportamento de Fenestra e usa un composition recursive pro que sia possibile appender tante "revestimentos" de Decoratores quante on desira.

On pote crear tante Decorators como on vole per hereditar de FenestraDecorator.

 Exemplo C++ 

#include <iostream>

//[Classe Component] vider diagramma de classes
class IFenestraAbstracte
{
public:

	virtual void Delinear() = 0;
};

//[Classe ConcreteComponent] vider diagramma de classes, Classe que on desira decorar
class Fenestra : public IFenestraAbstracte
{
public:

	void Delinear()
	{
		std::cout << " Fenestra ";
	}
};

//[Classe Decorator] vider diagramma de classes
class FenestraDecorator : public IFenestraAbstracte
{
public:
	FenestraDecorator(IFenestraAbstracte* fenestraAbstracte)
	{
		_FenestraAbstracte = fenestraAbstracte;
	}

	virtual void Delinear() = 0;

protected:
	IFenestraAbstracte* _FenestraAbstracte;
};

//[Classe ConcreteDecorator] vider diagramma de classes
class BordoDecorator : public FenestraDecorator
{
public:
	BordoDecorator(IFenestraAbstracte* fenestraAbstracte) : FenestraDecorator(fenestraAbstracte)
	{
	}

	virtual void Delinear()
	{
		std::cout << "|";
		_FenestraAbstracte->Delinear();
		std::cout << "|";
	}
};

//[Classe ConcreteDecorator] vider diagramma de classes
class ButtonDeAdjutaDecorator : public FenestraDecorator
{
public:
	ButtonDeAdjutaDecorator(IFenestraAbstracte* fenestraAbstracte) : FenestraDecorator(fenestraAbstracte)
	{
	}

	virtual void Delinear()
	{
		_FenestraAbstracte->Delinear();
		std::cout << "[Button de Adjuta]";
	}
};

int main()
{
	ButtonDeAdjutaDecorator* fenestraConButtonDeAdjuta = new ButtonDeAdjutaDecorator(new Fenestra());
	fenestraConButtonDeAdjuta->Delinear();
	std::cout << std::endl;

	BordoDecorator* fenestraConButtonDeAdjutaEBordo = new BordoDecorator(fenestraConButtonDeAdjuta);
	fenestraConButtonDeAdjutaEBordo->Delinear();
	std::cout << std::endl;

	BordoDecorator* fenestraConBordo = new BordoDecorator(new Fenestra());
	fenestraConBordo->Delinear();
	std::cout << std::endl;

	BordoDecorator* fenestraConDupleBordo = new BordoDecorator(fenestraConBordo);
	fenestraConDupleBordo->Delinear();
	std::cout << std::endl;

	delete fenestraConButtonDeAdjuta;
	delete fenestraConButtonDeAdjutaEBordo;
	delete fenestraConBordo;
	delete fenestraConDupleBordo;

	return 0;
}

 Exemplo C# 

using System;
using System.Collections.Generic;
using System.Text;

namespace Decorator
{
	class Program
	{
		static void Main(string[] args)
		{
			BordoDecorator fenestraConButtonDeAdjutaEBordo = new BordoDecorator(fenestraConButtonDeAdjuta);
			fenestraConButtonDeAdjutaEBordo.Delinear();
			Console.WriteLine();

			BordoDecorator fenestraConBordo = new BordoDecorator(new Fenestra());
			fenestraConBordo.Delinear();
			Console.WriteLine();

			BordoDecorator fenestraConDupleBordo = new BordoDecorator(fenestraConBordo);
			fenestraConDupleBordo.Delinear();
			Console.WriteLine();

			Console.Read();
		}

		//[Classe Component] vider diagramma de classes
		public interface IFenestraAbstracte
		{
			void Delinear();
		}

		//[Classe ConcreteComponent] vider diagramma de classes, Classe que on desira decorar
		public class Fenestra : IFenestraAbstracte
		{
			public void Delinear() 
			{
				Console.Write(" Fenestra ");
			}
		}

		//[Classe Decorator] vider diagramma de classes
		public abstract class FenestraDecorator : IFenestraAbstracte
		{
			public FenestraDecorator(IFenestraAbstracte fenestraAbstracte) 
			{ 
				_FenestraAbstracte = fenestraAbstracte;
			}

			protected IFenestraAbstracte _FenestraAbstracte;

			public abstract void Delinear();
		}

		//[Classe ConcreteDecorator] vider diagramma de classes
		public class BordoDecorator : FenestraDecorator
		{
			public BordoDecorator(IFenestraAbstracte fenestraAbstracte) : base(fenestraAbstracte) 
			{
			}

			public override void Delinear() 
			{
				Console.Write("|");
				_FenestraAbstracte.Delinear();
				Console.Write("|");
			}            
		}

		//[Classe ConcreteDecorator] vider diagramma de classes
		public class ButtonDeAdjutaDecorator : FenestraDecorator
		{
			public ButtonDeAdjutaDecorator(IFenestraAbstracte fenestraAbstracte) : base(fenestraAbstracte) 
			{
			}

			public override void Delinear() 
			{
				_FenestraAbstracte.Delinear();
				Console.Write("[Button de Adjuta]");
			}            
		}
	}
}

 Exemplo Java 

public abstract class Componente
{
	abstract public void operation();
}

public class ComponenteConcrete extends Componente
{
	public void operation()
	{
		System.out.println("ComponenteConcrete.operation()");
	}
}

public abstract class Decorator extends Componente
{
	private Componente _componente;

	public Decorator(Componente componente)
	{
		_componente = componente;
	}

	public void operation()
	{
		_componente.operation();
	}
}

public class DecoratorConcreteA extends Decorator
{
	private String _proprietateAppendite;

	public DecoratorConcreteA(Componente componente)
	{
		super(componente);
	}

	public void operation()
	{
		super.operation();
		_proprietateAppendite = "Nove proprietate";
		System.out.println("DecoratorConcreteA.operation()");
	}
}

public class DecoratorConcreteB extends Decorator
{
	public DecoratorConcreteB(Componente componente)
	{
		super(componente);
	}

	public void operation()
	{
		super.operation();
		comportamentoAppendite();
		System.out.println("DecoratorConcreteB.operation()");
	}

	public void comportamentoAppendite()
	{
		System.out.println("Comportamento B appendite");
	}
}

public class Cliente
{
	public static void main(String[] args)
	{
		ComponenteConcrete c = new ComponenteConcrete();
		DecoratorConcreteA d1 = new DecoratorConcreteA(c);
		DecoratorConcreteB d2 = new DecoratorConcreteB(d1);
		d2.operation();
	}
}

 Exemplo Python 

def establir_costo_decorator(function):
	def copertura1(instantia, costo):
		function(instantia, costo)
	return copertura1

def obtener_costo_decorator(costo_additional):
	def copertura1(function):
		def copertura2(instantia):
			return function(instantia) + costo_additional
		return copertura2
	return copertura1

class Caffe(object):
	@establir_costo_decorator
	def establir_costo(self, costo):
		self.costo = costo

	@obtener_costo_decorator(0.5)
	@obtener_costo_decorator(0.7)
	@obtener_costo_decorator(0.2)
	def obtener_costo(self):
		return self.costo

caffe = Caffe()
caffe.establir_costo(1.0)
print caffe.obtener_costo() # 2.4

 Exemplo de PHP 
<?php
interface iCoffee
{
	public function getBaseCost();
}

class Coffee implements iCoffee
{
	protected $_baseCost = 0;

	public function getBaseCost()
	{
		return $this->_baseCost;
	}
}

class BlackCoffee extends Coffee
{
	public function __construct()
	{
		$this->_baseCost = 5;
	}
}

abstract class CoffeeDecorator implements iCoffee
{
	protected $_coffee;

	public function __construct(iCoffee $Coffee)
	{
		$this->_coffee = $Coffee;
	}
}

class WithCream extends CoffeeDecorator
{
	public function getBaseCost()
	{
		return $this->_coffee->getBaseCost() + 1.5;
	}
}

class WithMilk extends CoffeeDecorator
{
	public function getBaseCost()
	{
		return $this->_coffee->getBaseCost() + 4;
	}
}

class WithChocolate extends CoffeeDecorator
{
	public function getBaseCost()
	{
		return $this->_coffee->getBaseCost() + 5;
	}
}

$coffee = new WithChocolate(new WithMilk(new WithCream(new BlackCoffee())));
echo 'Le precio del caffe es: $' . $coffee->getBaseCost();

 Ligamines externe 
  Patrono Decorator: explication e modello UML
  Patrono Decorator in PHP

Categoria:Patronos de designo