Неполностью реализованные паттерны Oop.
Green, приведи мне пример не полностью реализованного паттерна OOP. Мне чисто с научной точки зрения интересно.
Называй любой паттерн, приведу пример, как его реализовывать не полностью
Называй любой паттерн, приведу пример, как его реализовывать не полностью
паттерн Strategy.
паттерн Strategy.
Довольно простой паттерн, который тем не менее можно реализовать множеством различных способов.
Для начала стоит определить, что стратегии могут назначаться динамически, т.е. в процессе выполнения программы, а так же статически, т.е. на этапе компиляции.
Динамически применяемая стратеги в общем виде представляет собой систему классов включающую:
- интерфейс стратегии, абстрактный класс, либо класс содержащий дефолтовую реализацию некоторых методов;
- конкретные стратегии, порожденные от класса интерфейса;
- контекст, к которому применяется та или иная стратегия, имеющий механизм назначения стратегии и обычно связанный с конкретной стратегией через агрегацию указанеля на интерфейс стратегии.
В общем виде это выглядит так:
{
public:
virtual func1();
virtual func2();
};
class ConcreteStrategy1
{
public:
/*virtual*/ func1();
/*virtual*/ func2();
};
class ConcreteStrategy2
{
public:
/*virtual*/ func1();
/*virtual*/ func2();
};
class Context
{
private:
IStrategy* pStrategy;
public:
SetStrategy(IStrategy*);
};
Статически применяемые стратегии могут реализовываться через обычное наследование или агрегацию
{
};
class Context
{
ConcreteStrategy1 strategy;
};
При этом каждая конкретная стратегия должна обеспечивть весь набор базовых методов. Поэтому есть смысл наследовать конкретные стратегии от некоторой базовой, в которой определены и реализованы дефолтовые методы.
Другой вариант задания стратегии - это применение шаблонных и шаблонных шаблонных классов.
При их использовании отпадает необходимость полностью задавать базовый набор методов.
Связь контекста со стратегией так же реализуется через наследование или агрегацию, плюс непосредственное использование типа, т.к. обычно статегии не имеют состояния (не содержат данных и реализованы статическими методами).
Как видишь, даже такой примитивный паттерн, как стратегия может быть реализован множеством различных путей. При этом какждый из методов применяется непосредственно от условий и общей архитектуры системы, и может быть реализован так, как это целесообразно в каждом конкретном случае.
Одним словом, жесткой схемы нет. Есть общее понятие, примерное описание некоторой единицы проектирования.
Что же касается рефакторинга, то наглядно видно, что рефакторинг не является способом "приведения кода к конкретному паттерну", т.к. сам код зависит изначально от выбранного на этапе проектирования паттерна.
Довольно простой паттерн, который тем не менее можно реализовать множеством различных способов.
Для начала стоит определить, что стратегии могут назначаться динамически, т.е. в процессе выполнения программы, а так же статически, т.е. на этапе компиляции.
Динамически применяемая стратеги в общем виде представляет собой систему классов включающую:
- интерфейс стратегии, абстрактный класс, либо класс содержащий дефолтовую реализацию некоторых методов;
- конкретные стратегии, порожденные от класса интерфейса;
- контекст, к которому применяется та или иная стратегия, имеющий механизм назначения стратегии и обычно связанный с конкретной стратегией через агрегацию указанеля на интерфейс стратегии.
В общем виде это выглядит так:
{
public:
virtual func1();
virtual func2();
};
class ConcreteStrategy1
{
public:
/*virtual*/ func1();
/*virtual*/ func2();
};
class ConcreteStrategy2
{
public:
/*virtual*/ func1();
/*virtual*/ func2();
};
Спасибо за ликбез. Хочу заметить что на этом определение паттерна Strategy кончается. Это можно утверждать проанализировав различные примеры применения паттерна Strategy. Именно эта часть является постоянной и неизменной - все остальное лишь тот или иной способ его задействования. Например:
{
private:
IStrategy* pStrategy;
public:
SetStrategy(IStrategy*);
};
Статически применяемые стратегии могут реализовываться через обычное наследование или агрегацию
{
};
class Context
{
ConcreteStrategy1 strategy;
};
Я думаю что надо отличать сам паттерн от способа его применения.
Еще хотелось бы заметить по поводу:
Статически применяемые стратегии могут реализовываться через обычное наследование...
{
};
Крайне плохое решение. Противоречит базовым принципам OOP. Context не есть разновидность Strategy. Это действительно где то так написано? Если да то плз ссылочку.
При этом каждая конкретная стратегия должна обеспечивть весь набор базовых методов. Поэтому есть смысл наследовать конкретные стратегии от некоторой базовой, в которой определены и реализованы дефолтовые методы.
Другой вариант задания стратегии - это применение шаблонных и шаблонных шаблонных классов.
При их использовании отпадает необходимость полностью задавать базовый набор методов.
Связь контекста со стратегией так же реализуется через наследование или агрегацию, плюс непосредственное использование типа, т.к. обычно статегии не имеют состояния (не содержат данных и реализованы статическими методами).
Еще раз спасибо за ликбез.
Как видишь, даже такой примитивный паттерн, как стратегия может быть реализован множеством различных путей. При этом какждый из методов применяется непосредственно от условий и общей архитектуры системы, и может быть реализован так, как это целесообразно в каждом конкретном случае.
Одним словом, жесткой схемы нет. Есть общее понятие, примерное описание некоторой единицы проектирования.
По всей видимости происходит подмена понятий "реализован" и "использован". Кроме того речь шла о "неполной реализации", а не о "вариантах использования".
Что же касается рефакторинга, то наглядно видно, что рефакторинг не является способом "приведения кода к конкретному паттерну", т.к. сам код зависит изначально от выбранного на этапе проектирования паттерна.
Скоко раз повторять : Я не утверждал что рефакторинг есть способ "приведения кода к конкретному паттерну". Не надо так примитивно интерпретировать мои слова. Во первых код изначально написанный по тому или иному общепризнаному паттерну вряд ли подлежит "рефакторизации" как то связанной с этим паттерном, так как общепризнананые паттерны как раз устроены так что бы избежать проблем (дублирование кода, запутанная логика...) которые как правило вызывают рефакторинг. Во вторых "рефакторизованный" код (без сознательного применения паттернов) как правило приводит к коду, после анализа которого выясняется что он соответсвует тому или иному паттерну. Но в частности в моей практике я так сказать "рефакторизировал" код как раз на предмет приведения его к тому или иному паттерну(ЯВНО). После это больше необходимостей в рефакторизации этого участка кода больше не возникало. Аминь.
Хочу заметить что на этом определение паттерна Strategy кончается.
На этом заканчивается образное описание лишь одного участника паттерна.
Ты путаешь описание всего паттерна и описание всего лишь одного участника, который носит тоже название, что и паттерн.
GoF:
Название
Strategy
Стратегия
паттерн поведения объектов
Участники
Strategy (Compositor) - стратегия:
- объявляет общий для всех поддерживаемых алгоритмов интерфейс. Класс Context пользуется этим интерфейсом для вызова конкретного алгоритма, определенного в классе ConcreteStratecjy;
ConcreteStrategy (SirnpleCompositor, TeXCompositor, ArrayCompositor) - конкретная стратегия:
- реализует алгоритм, использующий интерфейс, объявленный в классе Strategy;
Context (Composition) - контекст:
- конфигурируется объектом класса ConcreteStrategy;
- храпит ссылку на объект класса Strategy;
- может определять интерфейс, который позволяет объекту strategy получить доступ к данным контекста.
Крайне плохое решение. Противоречит базовым принципам OOP. Context не есть разновидность Strategy. Это действительно где то так написано? Если да то плз ссылочку.
А.Александреску, "Современное проектирование на С++" ("Modern C++ Design"), стр.31
1.5 Стратегии и классы стратегий
"Классы стратегий по отдельности не используются. Они либо наследуются другими классами, либо содержаться в них"
По всей видимости происходит подмена понятий "реализован" и "использован". Кроме того речь шла о "неполной реализации", а не о "вариантах использования".
Хорошо, давай согласуем понятия.
Использование - применение патерна, как архитектурной единицы при проектировании.
Реализация - написание кода на алгоритмическом языке представляющего функциональность паттерна.
"Неполная реализация" - это твоя формулировка, к которой я не имею отношения.
Само понятие "неполной реализации" не имеет смысла, т.к. паттерн это не что-то фиксированное, жестко лимитированное. Цитирую себя же:
Паттерн может быть реализован так и в той мере, как это нужно для поддержания целостности архитектуры и обеспечения функциональности.
При этом заметь нет смысла реализовфывать паттерн на все 100% (хотя бы потому, что это невозможно), достаточно реализовать его на столько, на сколько это необходимо. В этом и заключается отсутствие какой-то жесткости и четкой завершенности того или иного паттерна.
Во первых код изначально написанный по тому или иному общепризнаному паттерну вряд ли подлежит "рефакторизации" как то связанной с этим паттерном, так как общепризнананые паттерны как раз устроены так что бы избежать проблем (дублирование кода, запутанная логика...) которые как правило вызывают рефакторинг.
Любой из "общепризнанных паттернов" можно реализовать множеством способов и т.о. сама реализация подлежит рефакторингу.
Но в частности в моей практике я так сказать "рефакторизировал" код как раз на предмет приведения его к тому или иному паттерну(ЯВНО).
Значит, изначально код не был спроектирован.
Приведение готового кода к паттерну, - это подгонка под ответ, что не есть правильно. Я уже говорил об этом, что при нормальном проектировании пляшут от обратного: сначала проектируют на уровне паттернов, потом реализуют в виде кода.
После это больше необходимостей в рефакторизации этого участка кода больше не возникало. Аминь.
Да будет земля пухом этому коду.
P.S. Что там с сабклассингом без внедрения?
На этом заканчивается образное описание лишь одного участника паттерна.
Ты путаешь описание всего паттерна и описание всего лишь одного участника, который носит тоже название, что и паттерн.
GoF:
Ничего я не путаю. Мне кажется ты не понимаешь сути паттерна Strategy. Классы Context и Client - всего лишь способ задействования IStrategy, основная суть паттерна именно в этом как ты говоришь всего лишь только участнике. На самом деле в неигрушечных примерах классы Context и Client строго говоря не являются только учасниками данного паттерна. В частности в моем текущем проекте(файловый менеджер) класс Context - он же участник(как ты выражаешься, я думаю может - соучастник :D), друго паттерна - Mediator, он же основное окно, и у него даже есть Client - CWinApp. Если же придерживаться строго формальных определений до можно договориться до полного бреда, примеров тому в юриспруденции наверное миллионы, но мы же не в американском суде? :D
На самом деле в неигрушечных примерах классы Context и Client строго говоря не являются только учасниками данного паттерна. В частности в моем текущем проекте(файловый менеджер) класс Context - он же участник(как ты выражаешься, я думаю может - соучастник :D), друго паттерна - Mediator, он же основное окно, и у него даже есть Client - CWinApp.
Правильно, это ещё раз подтверждает, что паттерны - это всего лишь способ описания архитектуры, а не готовое законченное решение.
Границы паттерна не являются границами класса или классов. Другими словами, класс может входить в несколько паттернов, реализовывать в каждом из них нескольких участников. Обычно так и происходит, т.е. как я утверждаю с самого начала, ВСЁ ЗАВИСИТ ОТ КОНКРЕТНОЙ РЕАЛИЗАЦИИ.
Кстати, я свои утверждения подтверждаю документально. Ты просил ссылки, ты их получил.
Я же от тебя ещё не получил ни одного подтверждения, конкретного примера (это я про сабклассинг). Одно теоретизирование...
Докажи мне, плз, документально, что
код изначально написанный по тому или иному общепризнаному паттерну вряд ли подлежит "рефакторизации"
Ну а вообще-то, мне уже надоело это толчение воды в ступе. Если ты считаешь, что твоё видиние паттернов правильное, - удачи, я отговаривать не собираюсь... с моим то отрицательным IQ...