blob: 3fabcd49025722611e39314d78cd5be7b44292ce (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
|
#pragma once
#include <memory>
namespace smtp::message_builder::types
{
/**
* @brief Базовый интерфейс описания декоратора
* @details См. https://refactoring.guru/ru/design-patterns/decorator
* @tparam T Тип декорируемого класса, T должен обладать возможностью наследования (в том числе виртуальный деструктор)
*/
template < typename T, typename TPointerType = std::shared_ptr<T> > class IDecorator : public T
{
public:
using PointerType = TPointerType;
using Type = IDecorator<T, TPointerType>;
~IDecorator() override = default;
/**
* @brief Установить указатель на декорируемый класс
* @details По возможности используйте метод Apply() как наиболее универсальный
* @param base Указатель на декорируемый класс
*/
void SetBase( PointerType const& base ) noexcept
{
mBase = base;
}
void SetBase( PointerType&& base ) noexcept
{
mBase = std::move( base );
}
/**
* @brief Установить указатель на декорируемый класс (цепочка обязанностей)
* @details См. https://refactoring.guru/ru/design-patterns/chain-of-responsibility/cpp/example
* @details Цепь вызовов: декоратор1 -> декоратор2 -> базовый класс
* @param base_or_decorator Указатель на декорируемый класс или целевой декоратор
*/
Type& Apply( PointerType const& base_or_decorator ) noexcept
{
if( !base_or_decorator )
{
return *this;
}
SetBase( base_or_decorator );
return GetApplyResult();
}
Type& Apply( PointerType&& base_or_decorator ) noexcept
{
if( !base_or_decorator )
{
return *this;
}
SetBase( std::move( base_or_decorator ) );
return GetApplyResult();
}
private:
Type& GetApplyResult() noexcept
{
auto as_decorator = dynamic_cast< Type * >( mBase.get() );
if( as_decorator )
{
return *as_decorator;
}
return *this;
}
protected:
PointerType mBase;
};
template < typename T, typename TDeleter = std::default_delete<T> > using IDecoratorUnique = IDecorator<T, std::unique_ptr<T, TDeleter> >;
} // namespace sbis::devices::generic::types
|