Для реализации модификаторов доступа
public
в каждом отдельном классе декоратора, мы можем объявить поля и методы внутри этих классов с модификатором доступа
public
. Вот обновленный пример, где каждый класс декоратора содержит свои поля и методы с модификатором доступа
public
:
C#:
using System;
// Базовый интерфейс компонента
public interface IComponent
{
string Operation();
}
// Конкретный компонент (класс кофе)
public class Coffee : IComponent
{
public string Operation()
{
return "Coffee";
}
}
// Конкретный декоратор "Молоко"
public class MilkDecorator : IComponent
{
public IComponent Component { get; set; }
public MilkDecorator(IComponent component)
{
Component = component;
}
public string Operation()
{
return "Milk + " + Component.Operation();
}
}
// Конкретный декоратор "Ваниль"
public class VanillaDecorator : IComponent
{
public IComponent Component { get; set; }
public VanillaDecorator(IComponent component)
{
Component = component;
}
public string Operation()
{
return "Vanilla + " + Component.Operation();
}
}
// Конкретный декоратор "Сливки"
public class CreamDecorator : IComponent
{
public IComponent Component { get; set; }
public CreamDecorator(IComponent component)
{
Component = component;
}
public string Operation()
{
return "Cream + " + Component.Operation();
}
}
// Пример использования
class Program
{
static void Main()
{
IComponent coffee = new Coffee();
Console.WriteLine("Plain coffee: " + coffee.Operation());
IComponent coffeeWithMilk = new MilkDecorator(coffee);
Console.WriteLine("Coffee with milk: " + coffeeWithMilk.Operation());
IComponent coffeeWithMilkAndVanilla = new VanillaDecorator(coffeeWithMilk);
Console.WriteLine("Coffee with milk and vanilla: " + coffeeWithMilkAndVanilla.Operation());
IComponent coffeeWithMilkVanillaAndCream = new CreamDecorator(coffeeWithMilkAndVanilla);
Console.WriteLine("Coffee with milk, vanilla and cream: " + coffeeWithMilkVanillaAndCream.Operation());
}
}
В этом обновленном примере каждый класс декоратора (MilkDecorator, VanillaDecorator, CreamDecorator) содержит открытое свойство
Component
, а также реализует метод
Operation()
с модификатором доступа
public
. Каждый декоратор добавляет свой декорирующий функционал к базовому компоненту.
Сделай
/**
* Базовый интерфейс Компонента определяет поведение, которое изменяется
* декораторами.
*/
/**
* Базовый интерфейс Компонента определяет поведение, которое изменяется
* декораторами.
*/
class Component {
public:
virtual ~Component() {}
virtual std::string Operation() const = 0;
};
/**
* Конкретные Компоненты предоставляют реализации поведения по умолчанию. Может
* быть несколько вариаций этих классов.
*/
class ConcreteComponent : public Component {
public:
std::string Operation() const override {
return "ConcreteComponent";
}
};
/**
* Базовый класс Декоратора следует тому же интерфейсу, что и другие компоненты.
* Основная цель этого класса - определить интерфейс обёртки для всех конкретных
* декораторов. Реализация кода обёртки по умолчанию может включать в себя поле
* для хранения завёрнутого компонента и средства его инициализации.
*/
class Decorator : public Component {
/**
* @var Component
*/
protected:
Component* component_;
public:
Decorator(Component* component) : component_(component) {
}
/**
* Декоратор делегирует всю работу обёрнутому компоненту.
*/
std::string Operation() const override {
return this->component_->Operation();
}
};
/**
* Конкретные Декораторы вызывают обёрнутый объект и изменяют его результат
* некоторым образом.
*/
class ConcreteDecoratorA : public Decorator {
/**
* Декораторы могут вызывать родительскую реализацию операции, вместо того,
* чтобы вызвать обёрнутый объект напрямую. Такой подход упрощает расширение
* классов декораторов.
*/
public:
ConcreteDecoratorA(Component* component) : Decorator(component) {
}
std::string Operation() const override {
return "ConcreteDecoratorA(" + Decorator::Operation() + ")";
}
};
/**
* Декораторы могут выполнять своё поведение до или после вызова обёрнутого
* объекта.
*/
class ConcreteDecoratorB : public Decorator {
public:
ConcreteDecoratorB(Component* component) : Decorator(component) {
}
std::string Operation() const override {
return "ConcreteDecoratorB(" + Decorator::Operation() + ")";
}
};
/**
* Клиентский код работает со всеми объектами, используя интерфейс Компонента.
* Таким образом, он остаётся независимым от конкретных классов компонентов, с
* которыми работает.
*/
void ClientCode(Component* component) {
// ...
std::cout << "RESULT: " << component->Operation();
// ...
}
int main() {
/**
* Таким образом, клиентский код может поддерживать как простые компоненты...
*/
Component* simple = new ConcreteComponent;
std::cout << "Client: I've got a simple component:\n";
ClientCode(simple);
std::cout << "\n\n";
/**
* ...так и декорированные.
*
* Обратите внимание, что декораторы могут обёртывать не только простые
* компоненты, но и другие декораторы.
*/
Component* decorator1 = new ConcreteDecoratorA(simple);
Component* decorator2 = new ConcreteDecoratorB(decorator1);
std::cout << "Client: Now I've got a decorated component:\n";
ClientCode(decorator2);
std::cout << "\n";
delete simple;
delete decorator1;
delete decorator2;
return 0;
}