Форум программистов
 
Контакты: о проблемах с регистрацией, почтой и по другим вопросам пишите сюда - alarforum@yandex.ru, проверяйте папку спам! Обязательно пройдите активизацию e-mail.

Вернуться   Форум программистов > Технологии > Общие вопросы по программированию, компьютерным наукам
Регистрация

Восстановить пароль
Повторная активизация e-mail


Донат для форума - использовать для поднятия настроения себе и модераторам

А ещё здесь можно купить рекламу за 15 тыс руб в месяц! ) пишите сюда - alarforum@yandex.ru

Ответ
 
Опции темы
Старый 13.06.2009, 15:42   #11
pu4koff
ПрофессионалФорумчанин
 
Аватар для pu4koff
 
Регистрация: 22.05.2007
Сообщений: 9,483
Репутация: 3616
По умолчанию

Цитата:
Сообщение от atomicxp Посмотреть сообщение
Деструктор интерфейса защищён, значит нельзя вызвать его для объекта использующего интерфейс, через сам интерфейс и утечка памяти невозможна. Таким образом виртуальный деструктор не нужен.
Получили мы объект посредством вызова фабричного метода как указатель на интерфейс. Как тогда удалить этот объект, когда он станет ненужным?
pu4koff вне форума   Ответить с цитированием
Старый 13.06.2009, 16:13   #12
atomicxp
Форумчанин
 
Аватар для atomicxp
 
Регистрация: 01.05.2009
Сообщений: 110
Репутация: 63

skype: atomicxp
Печаль

Цитата:
Сообщение от pu4koff Посмотреть сообщение
Получили мы объект посредством вызова фабричного метода как указатель на интерфейс. Как тогда удалить этот объект, когда он станет ненужным?
В этом и заключается идея, запретить удалять объект через интерфейсы. В данном случае удаление возможно только с помощью вызова delete посредством указателя на объект, но не через указатель интерфейса ссылающийся на этот объект.

То есть если нужно удалять объект через интерфейсы, то можно включить виртуальный деструктор. А если не надо, то вот таким способом это запретить. Мне думается что понятие интерфейса подразумевает, что мы не будет удалять объект через интерфейсы, так как смысла в этом нет.

Ведь интерфейс создан для управления и ему лишь временно передаётся возможность управления объектом. Что будет если использовать более одного интерфейса на объекте, потом удалить одним из них объект и попытаться использоваться другой интерфейс. Будет ошибка.
atomicxp вне форума   Ответить с цитированием
Старый 13.06.2009, 17:43   #13
atomicxp
Форумчанин
 
Аватар для atomicxp
 
Регистрация: 01.05.2009
Сообщений: 110
Репутация: 63

skype: atomicxp
Лампочка Delegation pattern/Шаблон делегирования

Переходим к следующему шаблону проектирования так же принадлжащему к типу основных шаблонов (Fundamental)

* Delegation pattern/Шаблон делегирования

Оригинальничать не будем, потому сразу определение из вики:

Цитата:
Сообщение от wiki
В разработке ПО, шаблон делегирования (англ. delegation pattern) — это способ, которым объект внешне выражает некоторое поведение, но в реальности передаёт ответственность за выполнение этого поведения связанному объекту. Шаблон делегирования является фундаментальной абстракцией которая поддерживает композицию (также называемую агрегацией), примеси (mixins) и аспекты (aspects).
Та же вики сообщает о минусах
Цитата:
Сообщение от wiki
Этот шаблон обычно затрудняет оптимизацию по скорости в пользу улучшенной чистоты абстракции.
Плюсы и применимость не указана, но это и не важно, потому что данный шаблон наиболее часто используемый, так что не требует особых объяснений. Но раз уж я решил обсудить шаблоны, то придётся сделать это и для него.

Как уже было сказано, шаблон делегирования, так же известный как техника программирования включение-делегирование, ухудшает чистоту абстракций. Но здесь так же стоит отметить, что подобное негативное влияние можно сократить, а можно наоборот увеличить этот эффект. Под увеличением подразумеваются смешанные классы. Они очень сильно вредят чётким абстракциям.

Плюс заключается в возможности перестроения чужих алгоритмов под свои собственные. Таким образом можно перенести целые наборы библиотек. Именно так был построен .NET Framework, ведь рефлектор наглядно показывает, что шаблон делегирования используется в нём чуть ли не чаще, чем всё остальное. Аналогичным образом строится Mono, непроделегированные методы можно просто объявить неиспользуемыми.

Если проследить рефлектором историю изменения, то от версии 1.1 к версии 2.0 данная техника программирования стала использоваться для ухудшения абстракций самого дотнета. Хотя речь совсем не о том, в какую сторону двигается майкрософт, а о C++. Простейший пример делегирования:

Код:
#include <iostream>

using namespace std;

class ClassA
{
 public:
    void ma()
    {
        cout << "ClassA: Method A" << endl;
    }
    void mb()
    {
        cout << "ClassA: Method B" << endl;
    }
};

class ClassB
{
 private:
    ClassA* classA;
 public:
    ClassB()
    {
        classA = new ClassA();
    }

    void ma()
    {
        classA->ma();
    }
    void mb()
    {
        classA->mb();
    }
};

void Testing()
{
    ClassA* classA = new ClassA();

    classA->ma();
    classA->mb();

    ClassB* classB = new ClassB();

    classB->ma();
    classB->mb();
}

int main()
{
    Testing();

    return 0;
}
А вот более интересное использование из вики:

Код:
#include <iostream>

using namespace std;

class I {
   public:
      virtual void f ( void ) = 0;
      virtual void g ( void ) = 0;
};

class A : public I {
   public:
      void f ( void ) { cout << "A: вызываем метод f()" << std::endl; }
      void g ( void ) { cout << "A: вызываем метод g()" << std::endl; }
};

class B : public I {
   public:
      void f ( void ) { cout << "B: вызываем метод f()" << std::endl; }
      void g ( void ) { cout << "B: вызываем метод g()" << std::endl; }
};

class C : public I {
   public:
     // Конструктор
      C() : i ( new A() ) { }
     // Деструктор
      virtual ~C() {
         delete i;
      }
      void f ( void ) { i -> f(); }
      void g ( void ) { i -> g(); }
     // Этими методами меняем поле-объект, чьи методы будем делегировать
      void toA ( void ) {
         delete i;
         i = new A();
      }
      void toB ( void ) {
         delete i;
         i = new B();
      }
   private:
     // Объявляем объект методы которого будем делегировать
      I * i;
};

int main ( void ) {
   C * c = new C();

   c -> f();
   c -> g();
   c -> toB();
   c -> f();
   c -> g();

   delete c;
   return 0;
}
Данный пример намного более интересен, создаются несколько классов и благодаря переключению с помощью интерфейса появляется возможность использовать в одном объекте одними методами совершенно разную реализацию.

Конечно, недостаток в том, что приходится переключать весь класс. Так же подобных результатов можно добиться указателями на функции, а не только интерфейсами. Как бы то ни было к шаблону делегирования это не относится.

Последний раз редактировалось atomicxp; 13.06.2009 в 17:44. Причина: Delegation pattern/Шаблон делегирования
atomicxp вне форума   Ответить с цитированием
Старый 13.06.2009, 20:43   #14
atomicxp
Форумчанин
 
Аватар для atomicxp
 
Регистрация: 01.05.2009
Сообщений: 110
Репутация: 63

skype: atomicxp
По умолчанию Immutable/Неизменяемый объект

Далее по плану следует Immutable/Неизменяемый объект. Для начала нужно сказать, что неизменяемость объекта достигается различными путями. Как только объект был инициализирован, он уже не должен изменятся с точки зрения пользователя этого объекта, и не важно, чем это выражено. Объект может быть как частично, так и полностью незименямым. Иногда это достигается ключевым словом const, в других случаях закрытыми полями и методом доступа с запретом изменять значения объекта.

Простейший случай использования:
Код:
#include <iostream>

using namespace std;

class ClassA
{
 private:
    int _value; // immutable field
 public:
    ClassA(const int& value)
    {
        _value = value;
    }
 public:
    int getValue() const // immutable using
    {
        return _value;
    }
};

void Testing()
{
    ClassA* classA = new ClassA(15);
    cout << "value = " << classA->getValue() << endl;
}

int main()
{
    Testing();

    return 0;
}
Неизменямость хоть и проста в использовании, но требует более детального рассмотрения.
atomicxp вне форума   Ответить с цитированием
Старый 13.06.2009, 21:21   #15
pu4koff
ПрофессионалФорумчанин
 
Аватар для pu4koff
 
Регистрация: 22.05.2007
Сообщений: 9,483
Репутация: 3616
По умолчанию

Если добавить в объект коллекцию (массив, список,...), то уже не всё так тривиально будет. Если изменить коллекцию, то изменится ли состояние объекта? Можно ли для константного объекта изменять отдельные элементы коллекции или нет? и т.д. Но всё это будет уже зависеть от конкретной задачи
pu4koff вне форума   Ответить с цитированием
Старый 13.06.2009, 21:55   #16
atomicxp
Форумчанин
 
Аватар для atomicxp
 
Регистрация: 01.05.2009
Сообщений: 110
Репутация: 63

skype: atomicxp
Сообщение введение в стереотипы

Цитата:
Сообщение от pu4koff Посмотреть сообщение
Если добавить в объект коллекцию (массив, список,...), то уже не всё так тривиально будет. Если изменить коллекцию, то изменится ли состояние объекта? Можно ли для константного объекта изменять отдельные элементы коллекции или нет? и т.д. Но всё это будет уже зависеть от конкретной задачи
Давай тогда для примера рассмотрим для чего же выделять шаблоны проектирования, и как это поможет в реальном деле. Если бы шаблоны проектирования были слишком сильно размыты и их нельзя выделить в стереотипы, нам бы незачем было о них говорить. Взглянем на UML отображение класса, которое я сделал.



Не знаю насколько оно точно соответствует принятым понятиям, хотя и прочёл книгу про UML. Как раз эта одна из целей, которой нужно добиться, а именно чёткое соответствие графического вида и конкретной реализации. Причём дело не в детализации, графический вид может иметь её в меньшей степени, а в неукоснительном следовании уже принятым понятиям.

Стереотипы традиционно выделяются в <<>>, а # так понял означает закрытый. Стереотип <<Immutable>> в данном случае отнёс вовсе не к классу, а к методу. Иными словами шаблоны проектирования бывают разными и относятся к разным частям класса.

Поскольку уже было рассмотрено три шаблона, то возникает вопрос, можно ли комбинировать какие-либо из них. Если взять тот же интерфейс, то его стереотип был бы записан наверху, заместо слова <<stereotype>> находилось бы <<Interface>>.

А вот шаблон делегирования и неизменяемости относятся к методам, особенно если исходить, что включённые (агрегированные) объекты брать всегда используя методы, а сами объекты делать закрытыми или защищёнными. Иными словами пользоваться свойствами (присвоение или извлечение объекта с проверкой), ведь даже там где они имеют другой вид, например, .NET, на самом деле создаются методы с приставкой get/set.

Может ли в методе быть <<immutable delegation>>, очевидно да. Даже в таких размытых шаблонах проектирования можно добиться определённости. Причём как видно, шаблоны этих же категорий, а так же многих других, имеют более чёткое определение и вообще не комбинируются вместе.
atomicxp вне форума   Ответить с цитированием
Старый 14.06.2009, 18:28   #17
atomicxp
Форумчанин
 
Аватар для atomicxp
 
Регистрация: 01.05.2009
Сообщений: 110
Репутация: 63

skype: atomicxp
Сообщение Property Container/Контейнер свойств

Основные шаблоны (Fundamental)

* Delegation pattern/Шаблон делегирования
* Functional design/Шаблон функционального дизайна
* Immutable/Неизменяемый объект
* Interface
* Marker interface
* Property Container

Property Container/Контейнер свойств

Ниже представлен простейший пример с закрытым значением поля, который хранит свойство. Два метода, один называется accessor, имеет приставку get и извлекает значение. Другой называется mutator, имеет приставку set и изменяет значение.

Код:
#include <iostream>

using namespace std;

class ClassA
{
 private:
    int _value; // property field
 public:
    ClassA()
    {
        _value = 0;
    }
 public:
    int getValue() const // accessor
    {
        // get property
        return _value;
    }
    void setValue(const int& value) // mutator
    {
        // check & assignment property
        _value = value;
    }
};

int main()
{
    ClassA* classA = new ClassA();
    cout << classA->getValue() << endl;
    classA->setValue(15);
    cout << classA->getValue() << endl;

    return 0;
}
Так же стоит отметить, что в реальности данные могут хранится где угодно, не обязательно в закрытом поле, и быть в любом виде. За их проверку и перобразование отвечает accessor и mutator, в простейшем случае я не стал использовать дополнительные возможности, которые они предоставляют. В сложных случаях могут использоватся инструкции ветвления, а так же выбрасываться исключения.
atomicxp вне форума   Ответить с цитированием
Старый 14.06.2009, 19:52   #18
pu4koff
ПрофессионалФорумчанин
 
Аватар для pu4koff
 
Регистрация: 22.05.2007
Сообщений: 9,483
Репутация: 3616
По умолчанию

Таки для наглядности в "мутаторе" можно проверку какую-нибудь всеже написать:
Код:
если (value < 0) то выкинуть исключение.
Читабельность примера такой же останется, но у новичков не возникнет вопроса: "нафига вообще это надо и почему бы не сделать тупо _value public'ом?"
pu4koff вне форума   Ответить с цитированием
Старый 14.06.2009, 22:13   #19
atomicxp
Форумчанин
 
Аватар для atomicxp
 
Регистрация: 01.05.2009
Сообщений: 110
Репутация: 63

skype: atomicxp
Радость соблюдение чистоты абстракии

Цитата:
Сообщение от pu4koff Посмотреть сообщение
Таки для наглядности в "мутаторе" можно проверку какую-нибудь всеже написать:
Код:
если (value < 0) то выкинуть исключение.
Читабельность примера такой же останется, но у новичков не возникнет вопроса: "нафига вообще это надо и почему бы не сделать тупо _value public'ом?"
Здесь всё не так просто, да и тема не для новичков. То что у тебя описано скорее всего проверка на допустимость диапазона значений, и исключение кидается именно для этого. А значит нужно создавать класс исключения проверяющий диапазон, и весь такой механизм будет единым целым идя от некоего общего начала.

В нём так же будут использоваться посторонние элементы, такие как сравнитель (comparer, comparator) и так далее, которые тоже являются частью некой системы. Для простоты, конечно, можно написать, что-то вроде, если недопустимое условие бросить исключение, а дальше просто описать извлечение или присвоение данных, но это был бы не лучший выход в свете рассмотрения шаблонов, ведь применяя их нужно действовать совсем по другому.

Основной смысл моих рассуждений выделить шаблоны проектирования и согласовать их с конкретной реализацией на языке C++ для кроссплатформенного программирования. Если что-то выходит за рамки рассматриваемого шаблона, то лучше это не писать.
atomicxp вне форума   Ответить с цитированием
Старый 14.06.2009, 22:49   #20
atomicxp
Форумчанин
 
Аватар для atomicxp
 
Регистрация: 01.05.2009
Сообщений: 110
Репутация: 63

skype: atomicxp
Вопрос Последние основные шаблоны проектирования

Осталось обсудить два шаблона проектирования:

* Functional design/Шаблон функционального дизайна
* Marker interface/Разметочный интерфейс

Шаблон функционального дизайна гласит, что класс должен отвечать за минимальную область деятельности. Любители смешанных классов (миксов) нарушают этот фундаментальный принцип, уменьшая степень абстракции.

В конце концов если смешанные классы перерастают в божественные, ни о какой абстракции системы говорить не приходится. Такую технику программирования можно воспринимать как псевдо объекто-ориентированное программирование.

Существует ряд рекомендованных правил для этого шаблона. Одно из них правило семи - в классе нужно стараться держать не более семи элементов. Контейнер свойств из двух методов можно воспринимать как один элемент. Даже если они ссылаются на включённый (агрегированный) класс, это все равно не три элемента, а один.

Если элементов стало больше семи, то это не значит, что нужно немедленно начать всё делить. Это значит, что надо задуматься над реализацией, возможно в ней что-то неправильно, и она нуждается в перепроектировании. Так же стоит следить за чистотой реализации, не допускать чрезмерного смешения шаблонов проектирования, которые для этого не предназначены.

Разметочный интерфейс позволяет получить дополнительные данные о классах, то есть метаданные (данные о данных). В некоторых системах текущий шаблон проектирования известен как рефлексия. Реализовывается различными способами, например, атрибутами.

Что касается C++, то пока мне трудно назвать лучший способ их реализации, а вариантов довольно много. Хотя напрашивается очевидный вывод использовать для этого интерфейсы, реализация которых уже была описана выше, с проверкой на их существование.

Впрочем пока оставлю это на обсуждение. Если кто думает, что знает, какая из реализаций лучше и приемлемей, чем другая, пусть запостит в эту тему код.
atomicxp вне форума   Ответить с цитированием
Ответ

Опции темы

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход

Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Паттерны проектирования shinauri PHP 0 17.07.2012 17:06
Консольный текстовый редактор и паттерны delias C# (си шарп) 0 22.04.2011 00:41
паттерны для детсада pproger Общие вопросы по программированию, компьютерным наукам 4 11.04.2011 19:40
паттерны проектирования prokach Общие вопросы C/C++ 3 18.01.2011 23:23


15:17.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2019, Jelsoft Enterprises Ltd.

Проекты отопления, пеллетные котлы, бойлеры, радиаторы
интернет магазин respective.ru