Դեկորատոր (նախագծման ձևանմուշ)

Դեկորատոր (), կառուցվածքային նախագծման ձևանմուշ, որը նախատեսված է օբյեկտներին դինամիկ կերպով նոր վարք ավելացնելու համար։ Դեկորատոր ձևանմուշը դասի ֆունկցիոնալությունը մեծացնելու նպատակով ենթադասերի ստեղծման ճկուն այլընտրանք է հանդիսանում։

Ընդհանուր հասկացողություններ
 Client - հայցող
 Instance - նմուշ
 Implementation - իրականացում
 Product - արգասիք

Հիմնական բնութագիրներ

Խնդիր 
Օբյեկտը, որը պետք է օգտագործվի, իրականացնում է հիմնական ֆունկցիաները։ Բայց կարող է անհրաժեշտ լինել նրան ավելացնել որոշակի լրացուցիչ ֆունկցիոնալություն, որը կարող է օգտագործել հիմնական ֆունկցիոնալությունից առաջ, հետո և նույնիսկ հիմնական ֆունկցիոնալության փոխարեն։

Լուծման տարբերակ 
Դեկորատորը օբյեկտի ֆունկցիոնալության ընդլայնումը դիտարկում է առանց ենթադասերի ստեղծման։

Մասնակիցներ 
ConcreteComponent դաս, որտեղ Դեկորատորի միջոցով ավելացվում է նոր ֆունկցիոնալություն։ Որոշ դեպքերում բազային ֆունկցիոնալությունը ներկայացվում է դասերով, որոնք ստեղծվել են ConcreteComponent դասի կողմից։ Այդ դեպքերում ConcreteComponent արդեն կոնկրետ դաս չէ, այլ աբստրակտ է։ Component աբստրակտ դասը տալիս է ինտերֆեյս բոլոր այդ դասերի օգտագործման համար։

Հետևություն 
 Ավելացվող ֆունկցիոնալությունը իրագործվում է ոչ մեծ օբյեկտներում։ Առավելությունն այն է, որ այդ ֆունկցիոնալությունը դինամիկ կերպով ավելանում է ConcreteComponent հիմնական ֆունկցիոնալությունից առաջ կամ հետո։
 Թույլ է տալիս դասերի վերին հիերարխիայում խուսափել ֆունկցիոնալությունների գերծանրաբեռնումից
 Դեկորատորը և նրա բաղկացուցիչ մասերը իդենտիկ չեն։

Իրականացում 
Ստեղծվում է աբստրակտ դաս, որն իրենից ներկայացնում է ելակետային դաս։ Ինչպես նաև ստեղծվում են նրո դասեր, որոնք ավելացվում են ֆունկցիայի դասի մեջ։ Դաս-դեկորատորներում նոր ֆունկցիաները կանչվում են ըստ հարկ եղած հերթականության՝ հերթական օբյեկտի կանչից առաջ կամ հետո։

Ցանկության դեպքում հնարավոր է նաև օգտագործել ելակետային դասը (առանց ֆունկցիոնալության ընդարձակման), եթե նրա օբյեկտի վրա պահպանվել է հղումը։

Ձևանմուշի կիրառություն 
Windows-ի կորիզում դրայվեր-ֆիլտրերն (WDM (Windows Driver Model) ճարտարապետություն) իրենցից ներկայացնում են դեկորատորներ։ Չնայած նրան, որ WDM-ն իրականացրած է Objective-C ծրագրավորման լեզվով, նրանցում հստակորեն հետևել են դեկորատոր ձևանմուշի կիրառմանը։

COM (Component Object Model) ճարտարապետությունը չի սպասարկում ժառանգումը։ Դրա փոխարեն այն առաջարկում է դեկորատորներ (կոնկերտ ճարտարապետության մեջ այն կոչվում է «ագրեգացիա»)։

Օրինակներ

C++ 
#include <iostream>
#include <memory>
 
class IComponent {
public:
	virtual void operation() = 0;
        virtual ~IComponent(){}
};
 
class Component : public IComponent {
public:
	virtual void operation() {
		std::cout<<"World!"<<std::endl;
	}
};
 
class DecoratorOne : public IComponent {
	std::shared_ptr<IComponent> m_component;
 
public:
	DecoratorOne(IComponent* component): m_component(component) {}
 
	virtual void operation() {
		std::cout << ", ";
		m_component->operation();
	}
};
 
class DecoratorTwo : public IComponent {
	std::shared_ptr<IComponent> m_component;
 
public:
	DecoratorTwo(IComponent* component): m_component(component) {}
 
	virtual void operation() {
		std::cout << "Hello";
		m_component->operation();
	}
};
 
int main() {
	DecoratorTwo obj(new DecoratorOne(new Component()));
	obj.operation(); // prints "Hello, World!\n"
 
	return 0;
}

C# 
using System;

namespace Decorator
{
    class MainApp
    {
        static void Main()
        {
            // Create ConcreteComponent and two Decorators
            ConcreteComponent c = new ConcreteComponent();
            ConcreteDecoratorA dA = new ConcreteDecoratorA();
            ConcreteDecoratorB dB = new ConcreteDecoratorB();

            // Link decorators
            dA.SetComponent(c);
            dB.SetComponent(dA);

            dA.Operation();

            Console.WriteLine();

            dB.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.Write("Привет");
        }
    }

    /// <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>
    /// ConcreteDecoratorA - конкретный декоратор
    /// </summary>
    /// <remarks>
    /// <li>
    /// <lu>Выполняет основную задачу</lu>
    /// </li>
    /// </remarks>
    class ConcreteDecoratorA : Decorator
    {
        public override void Operation()
        {
            base.Operation();
        }
    }

    /// <summary>
    /// ConcreteDecorator - конкретный декоратор
    /// </summary>
    /// <remarks>
    /// <li>
    /// <lu>Выполняет основную задачу + дополнительную</lu>
    /// </li>
    /// </remarks>
    class ConcreteDecoratorB : Decorator
    {
        public override void Operation()
        {
            base.Operation();

            Console.Write(" Мир!");
        }
    }
}

Java 
public interface InterfaceComponent {
	void doOperation();
}

class MainComponent implements InterfaceComponent {
	
	@Override
	public void doOperation() {
		System.out.print("World!");
	}	
}

abstract class Decorator implements InterfaceComponent {
	protected InterfaceComponent component;
	
	public Decorator (InterfaceComponent c) {
		component = c;
	}
	
	@Override
	public void doOperation() {
		component.doOperation();
	}
	
    public void newOperation() {
            System.out.println("Do Nothing");
    }
}

class DecoratorSpace extends Decorator{
	
	public DecoratorSpace(InterfaceComponent c) {
		super(c);
	}
	
	@Override
	public void doOperation() {
		System.out.print(" ");
		super.doOperation();
	}
	
    @Override
    public void newOperation() {
            System.out.println("New space operation");
    }	
}

class DecoratorComma extends Decorator {

	public DecoratorComma(InterfaceComponent c) {
		super(c);
	}
	
	@Override
	public void doOperation() {
		System.out.print(",");
		super.doOperation();
	}	
        
    @Override
    public void newOperation() {
            System.out.println("New comma operation");
    }
}

class DecoratorHello extends Decorator {
	
	public DecoratorHello(InterfaceComponent c) {
		super(c);
	}
	
	@Override
	public void doOperation() {
		System.out.print("Hello");
		super.doOperation();
	}
	
    @Override
    public void newOperation() {
            System.out.println("New hello operation");
    }
}

class Main {
	
	public static void main (String... s) {
		Decorator c = new DecoratorHello(new DecoratorComma(new DecoratorSpace(new MainComponent())));
		c.doOperation(); // Ծրագրի կատարման արդյունքը "Hello, World!"
	        c.newOperation(); // New hello operation
        }
}

Ծանոթագրություններ 

Ծրագրավորում