Начало здесь: C++ Паттерн проектированя "Стратегия".
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 |
//Листинг #1 Реализация по типу "Стратегия" //g++ 7.4.0 #include <iostream> class MemoryManager{ //класс, выполняющий роль интерфейса public: }; /*ПРЕДПОЛАГАЕМЫЕ СТРАТЕГИИ*/ class MemoryAllocate{ public: }; class MemoryFree{ public: }; /*КОНЕЦ ПРЕДПОЛАГАЕМЫХ СТРАТЕГИЙ*/ class Array{ //класс, выполняющий роль массива int *arr; //указатель как основной массив MemoryManager *manager; //объект, которому будет делегироваться управление памятью public: }; int main() { } |
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 |
//Листинг #2 //g++ 7.4.0 #include <iostream> class MemoryManager{ //класс, выполняющий роль интерфейса public: virtual void memory_operation() = 0; }; /*ПРЕДПОЛАГАЕМЫЕ СТРАТЕГИИ*/ class MemoryAllocate{ public: void memory_operation(){ } }; class MemoryFree{ public: void memory_operation(){ } }; /*КОНЕЦ ПРЕДПОЛАГАЕМЫХ СТРАТЕГИЙ*/ class Array{ //класс, выполняющий роль массива int *arr; //указатель как основной массив MemoryManager *manager; //объект, которому будет делегироваться управление памятью public: void execute_memory_operation(MemoryManager *m){ manager = m; //заказываем объекту manager стратегию m } }; int main() { } |
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 |
//Листинг #3 //g++ 7.4.0 #include <iostream> class MemoryManager{ //класс, выполняющий роль интерфейса public: virtual void memory_operation(int *&arr, const int size) = 0; //Для того, чтобы работать не с копией указателя, параметр ссылка на указатель virtual ~MemoryManager() = default; }; /*ПРЕДПОЛАГАЕМЫЕ СТРАТЕГИИ*/ class MemoryAllocate: public MemoryManager{ public: void memory_operation(int *&arr, const int size){ } }; class MemoryFree: public MemoryManager{ public: void memory_operation(int *&arr, const int size){ } }; /*КОНЕЦ ПРЕДПОЛАГАЕМЫХ СТРАТЕГИЙ*/ class Array{ //класс, выполняющий роль массива int *arr; //указатель как основной массив MemoryManager *manager; //объект, которому будет делегироваться управление памятью public: void execute_memory_operation(MemoryManager *m, const int size){ manager = m; //заказываем объекту manager стратегию m manager -> memory_operation(arr, size); //объект manager делает операцию с памятью, работает с классом MemoryManager } }; int main() { MemoryManager *alloc = new MemoryAllocate(); MemoryManager *clear = new MemoryFree(); Array *a = new Array(); //Чтобы можно было работать с объектом, объект должен существовать // int current_size = 10; a -> execute_memory_operation(alloc, current_size); //Выполняем предполагаемые стратегии a -> execute_memory_operation(clear, current_size); delete a; delete clear; delete alloc; } |
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 |
//Листинг #4 //g++ 7.4.0 #include <iostream> class MemoryManager{ //класс, выполняющий роль интерфейса public: virtual void memory_operation(int *&arr, const int size) = 0; //Для того, чтобы работать не с копией указателя, параметр ссылка на указатель virtual ~MemoryManager() = default; }; /*ПРЕДПОЛАГАЕМЫЕ СТРАТЕГИИ*/ class MemoryAllocate: public MemoryManager{ public: void memory_operation(int *&arr, const int size){ } }; class MemoryFree: public MemoryManager{ public: void memory_operation(int *&arr, const int size){ } }; /*КОНЕЦ ПРЕДПОЛАГАЕМЫХ СТРАТЕГИЙ*/ class Array{ //класс, выполняющий роль массива int *arr; //указатель как основной массив MemoryManager *manager; //объект, которому будет делегироваться управление памятью public: void execute_memory_operation(MemoryManager *m, const int size){ manager = m; //заказываем объекту manager стратегию m manager -> memory_operation(arr, size); //объект manager делает операцию с памятью, работает с классом MemoryManager } void set_values(const int size){ //метод for (int i=0; i<size; i++){ arr[i] = i; } } void print(const int size){ for (int i=0; i<size; i++){ cout << arr[i] << ' '; } cout << '\n'; } }; int main() { MemoryManager *alloc = new MemoryAllocate(); MemoryManager *clear = new MemoryFree(); Array *a = new Array(); //Чтобы можно было работать с объектом, объект должен существовать // int current_size = 10; a -> execute_memory_operation(alloc, current_size); //Выполняем предполагаемые стратегии a -> execute_memory_operation(clear, current_size); delete a; delete clear; delete alloc; } |
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 |
//Листинг #5 //g++ 7.4.0 #include <iostream> using namespace std; class MemoryManager{ //класс, выполняющий роль интерфейса public: virtual void memory_operation(int *&arr, const int size) = 0; //Для того, чтобы работать не с копией указателя, параметр ссылка на указатель virtual ~MemoryManager() = default; }; /*ПРЕДПОЛАГАЕМЫЕ СТРАТЕГИИ*/ class MemoryAllocate: public MemoryManager{ public: void memory_operation(int *&arr, const int size){ arr = new int [size]; } }; class MemoryFree: public MemoryManager{ public: void memory_operation(int *&arr, const int size){ delete []arr; } }; /*КОНЕЦ ПРЕДПОЛАГАЕМЫХ СТРАТЕГИЙ*/ class Array{ //класс, выполняющий роль массива int *arr; //указатель как основной массив MemoryManager *manager; //объект, которому будет делегироваться управление памятью public: void execute_memory_operation(MemoryManager *m, const int size){ manager = m; //заказываем объекту manager стратегию m manager -> memory_operation(arr, size); //объект manager делает операцию с памятью, работает с классом MemoryManager } void set_values(const int size){ //метод for (int i=0; i<size; i++){ arr[i] = i; } } void print(const int size){ for (int i=0; i<size; i++){ cout << arr[i] << ' '; } cout << '\n'; } }; int main() { MemoryManager *alloc = new MemoryAllocate(); MemoryManager *clear = new MemoryFree(); Array *a = new Array(); //Чтобы можно было работать с объектом, объект должен существовать // int current_size = 10; a -> execute_memory_operation(alloc, current_size); //Выполняем предполагаемые стратегии a -> set_values(current_size); // записали в массив значения a -> print(current_size); //вывели значения на экран a -> execute_memory_operation(clear, current_size); delete a; delete clear; delete alloc; } |
В нашем случае мы получаем не равнозначную замену. Порядок действий может быть не гарантирован. В том случае, если неизвестно, на какую именно операцию указывает указатель, должный указывать на стратегии, можно получить первым действием освобождение памяти, т. е. освобождение не выделенной памяти. А если попробуем использовать нашу предполагаемую стратегию — выделение памяти в функции, то получим проблему освобождения:
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 83 84 85 |
//Листинг #6 //g++ 7.4.0 #include <iostream> using namespace std; class MemoryManager{ //класс, выполняющий роль интерфейса public: virtual void memory_operation(int *&arr, const int size) = 0; //Для того, чтобы работать не с копией указателя, параметр ссылка на указатель virtual ~MemoryManager() = default; }; /*ПРЕДПОЛАГАЕМЫЕ СТРАТЕГИИ*/ class MemoryAllocate: public MemoryManager{ public: void memory_operation(int *&arr, const int size){ arr = new int [size]; } }; class MemoryFree: public MemoryManager{ public: void memory_operation(int *&arr, const int size){ delete []arr; } }; /*КОНЕЦ ПРЕДПОЛАГАЕМЫХ СТРАТЕГИЙ*/ class Array{ //класс, выполняющий роль массива int *arr; //указатель как основной массив MemoryManager *manager; //объект, которому будет делегироваться управление памятью public: void execute_memory_operation(MemoryManager *m, const int size){ manager = m; //заказываем объекту manager стратегию m manager -> memory_operation(arr, size); //объект manager делает операцию с памятью, работает с классом MemoryManager } void set_values(const int size){ //метод for (int i=0; i<size; i++){ arr[i] = i; } } void print(const int size){ for (int i=0; i<size; i++){ cout << arr[i] << ' '; } cout << '\n'; } }; void some_func(MemoryManager *manager){ Array *a = new Array(); int current_size = 10; a -> execute_memory_operation(manager, current_size); //Выполняем предполагаемые стратегии a -> set_values(current_size); a -> print(current_size); //a -> execute_memory_operation(clear, current_size); //стратегия приходит в параметре, она параметр manager //в одной функции стратегия может быть только одна! Она уже заказана. Нельзя её переназначить. delete a; } int main() { MemoryManager *alloc = new MemoryAllocate(); MemoryManager *clear = new MemoryFree(); some_func(alloc); //внутри функции память выделится, но мы не сможем её почистить // some_func(clear); // попытка почистить память так приведёт к тому, что появиться новый голый указатель, к которому произойдёт delete [] delete clear; delete alloc; } |
Примеры схожих алгоритмов:
-выделение памяти разными способами
-разные способы произношения
-разные способы произвести подсчёт чего-либо
-разные способы произвести сортировку
Примеры разных алгоритмов:
-Произвести разные действия (сложить и вычесть, сложить и умножить…, сесть и прыгнуть, сказать и открыть окно).
-Произвести противоположные действия.
Добавить комментарий