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

Վիքիպեդիայից՝ ազատ հանրագիտարանից
Դեկորատոր
ՏեսակԿառուցվածքային
ՆշանակությունՕբյեկտներին դինամիկ կերպով նոր պարտականություններ ավելացնելու համար
Կառուցվածք
ԱռավելություններՀետևյալն են.
  • Կարիք չկա դասի ֆունկցիոնալությունն ըդլայնելու համար ստեղծել նոր ենթադասեր։
  • Հնարավորություն է տալիս դինամիկ կերպով ավելացնել նոր ֆունկցիոնալություն հիմնական ConcreteComponent ֆունկցիոնալությունից առաջ կամ հետո։
Նկարագրությունը ԳօՖի
"Design Patterns" գրքում
Այո

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

Ընդհանուր հասկացողություններ[խմբագրել | խմբագրել կոդը]

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

Հիմնական բնութագիրներ[խմբագրել | խմբագրել կոդը]

Խնդիր[խմբագրել | խմբագրել կոդը]

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

Լուծման տարբերակ[խմբագրել | խմբագրել կոդը]

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

Մասնակիցներ[խմբագրել | խմբագրել կոդը]

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

Հետևություն[խմբագրել | խմբագրել կոդը]

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

Իրականացում[խմբագրել | խմբագրել կոդը]

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

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

Ձևանմուշի կիրառություն[խմբագրել | խմբագրել կոդը]

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
        }
}

Ծանոթագրություններ[խմբագրել | խմբագրել կոդը]

  1. Gamma, Erich; և այլք: (1995). Design Patterns. Reading, MA: Addison-Wesley Publishing Co, Inc. էջեր 175ff. ISBN 0-201-63361-2.