Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Вопрос о проектировании  (Прочитано 14163 раз)
0 Пользователей и 1 Гость смотрят эту тему.
RMihael
Гость
« : 13-09-2003 08:53 » 

Как-то раз у меня возникла проблема -- как хранить в одном контейнере разнотипные элементы с частично несовместимыми интерфесами (в основном отличались только типом возвращаемого значения -- например pair<int,int> get_lims() и int get_lims() ) и единообразно их обрабатывать. Типы не имели общего родительского и ввести его естественным образом было нельзя. Тогда эту проблему я решил использованием Discriminated Union Александреску, но осадок на душе остался -- может можно было как-то попроще?
   Может кто-то сталкивался с такой проблемой раньше и успешно её решал? Напишите, плз.
Записан
NetRaider
Гость
« Ответ #1 : 15-09-2003 04:59 » 

Если интерфейсы можно модифицировать, тогда смотри в сторону Double Dispatch или паттерна Visitor.
Записан
Serega
Гость
« Ответ #2 : 19-09-2003 19:48 » 

Можно адаптер написать и через него работать
Записан
RMihael
Гость
« Ответ #3 : 20-09-2003 07:48 » 

Извините, что не отвечал, был в коммандировке.
Двойная диспетчеризация и Visitor не подходили, поскольку объекты надо было хранить в контейнере. Адаптор не подходил, поскольку интерфейсы отличались возвращаемыми типами -- или есть какой-то неочевидный финт?
Записан
Serega
Гость
« Ответ #4 : 20-09-2003 08:00 » 

Для того адаптер и нужен чтобы адаптировать интерфейс к единому
Записан
RMihael
Гость
« Ответ #5 : 20-09-2003 12:33 » 

Цитата: Serega
Для того адаптер и нужен чтобы адаптировать интерфейс к единому
Давай с кодом, для избежания недоразумений.
У меня было что-то на манер этого:
class StrictParameter
{
public:
  const string& get_val(void) const;
  const list<string>& get_lims(void) const;
}

class RangeParameter
{
public:
 double get_val(void) const;
 const pair<double, double>& get_lims(void) const
}

Какой адаптер ты предлагаешь?
PS: Насколько я помню этот шаблон там предполагается создание одного адаптера для одного класса. Как их тогда хранить в контейнере? Да и усложняет это здорово -- дополнительных классов много.
Записан
Serega
Гость
« Ответ #6 : 20-09-2003 19:20 » new

Классов не будет много, а сложностей будет только меньше, если это действительно нужно
Этим кодом ты мне ничего не сказал
Как это используется в программе ?
надо исходить из этого, а пока не понятно вообще для чего эти классы обьединять
Записан
RMihael
Гость
« Ответ #7 : 21-09-2003 10:51 » 

Корень зла в том, что эти разнородные объекты надо было хранить в одном контейнере. При создании адаптера для каждого из классов хранить их так не получится. Если приводить эти адаптеры к одному, например использовать fake vtable или переключение типов, то это достаточно сложно и тяжело расширяемо. Если есть какой-то простой способ сделать из нескольких адаптеров один то скажи, я такого придумать не могу.
Записан
Serega
Гость
« Ответ #8 : 21-09-2003 11:12 » 

Из того что-ты мне написал я вижу что типы никак не связаны
Возможно проблема как-раз в том, что ты собрался хранить обьекты этих типов вместе
Обьясни более подробно что ты хочешь реализовать, тогда и ответ будет более развернутым
Записан
RMihael
Гость
« Ответ #9 : 21-09-2003 13:16 » 

Цитата: Serega
Из того что-ты мне написал я вижу что типы никак не связаны
Возможно проблема как-раз в том, что ты собрался хранить обьекты этих типов вместе
Обьясни более подробно что ты хочешь реализовать, тогда и ответ будет более развернутым
Типы были связаны, но на концептуальном уровне, а не средствами языка. Каждый класс представлял собой некоторый диапазон(численный) или возможное качественное значение определённого параметра. Соответственно в классе параметра был контейнер с его диапазонами возможных значений. Частично интерфейсы совпадали, и это совпадение хотелось использовать прозрачно, но не обрезая остальной части интерфейса. Ситуация усугублялась тем, что на момент проектирования была большая вероятность того, что появится новый тип возможных значений (как позже и случилось).
Записан
Serega
Гость
« Ответ #10 : 21-09-2003 15:08 » 

Пример.
У нас есть класс A, мы с ним работаем и храним обьекты этого класса в контейнере
Потом у нас появляется класс B, с которым нам приходится работать и хранить обьекты вместе с обьектами класса А
Насколько я понимаю это означает что классы A и B для клиента неразличимы, т.к. работать он с ними будет одинаково (об обратном не сказано ни слова)
Первое что приходит на ум в данной ситуации это адаптер, что-то типа
Код:
class AdaptBtoA { public A
|
    B* inner;
public{
    AdaptBtoA)B* toAdapt: { inner)toAdapt: |"
    ... // Переадресация вызовов inner
"

Если же при добавлении B придется править клиента, тогда лучше использовать визитор ИМХО
Записан
NetRaider
Гость
« Ответ #11 : 22-09-2003 00:35 » 

Цитата

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


Если типы были связаны на концептуальном уровне, то почему эта связь не отражена в коде ? Базовые классы надо вводить - и при добавлении новых типов заморочек не будет. Можно, конечно изобрести свой метод хранения разных типов в контейнере, но пострадает быстродействие, читабельность, и типобезопасноть. Если действительно надо то как вариант boost::any + свой аналог RTTI. Хотя необходимость определения типа в runtime, IMHO design fault.
Записан
RMihael
Гость
« Ответ #12 : 25-09-2003 18:21 » 

Цитата
Если типы были связаны на концептуальном уровне, то почему эта связь не отражена в коде ? Базовые классы надо вводить - и при добавлении новых типов заморочек не будет.

Связи на уровне языка не было из-за того самого design fault. Когда выяснилось, что их надо смешивать то было уже два отдельных класса и много кода. Базовый класс вводить я не стал, потому что проблема меня захватила и решение я нашёл -- оказалось достаточно удобное, хотя и не без недостатков. Просто сейчас стало интерестно, кто как решал такие проблемы.
Цитата
Если действительно надо то как вариант boost::any + свой аналог RTTI.

Я использовал Discriminated Union -- типобезопастный и более мощный вариант boost::any.
Цитата
Хотя необходимость определения типа в runtime, IMHO design fault.

Ну если тщательно заинкапсулировать, то можно. Дельфисты, Явщики используют и не ругаются. Хотя некрасиво конечно.
Записан
RMihael
Гость
« Ответ #13 : 25-09-2003 19:15 » 

Цитата
...Первое что приходит на ум в данной ситуации это адаптер, что-то типа...
Скорее всего как-то так я бы и поступил, если бы у меня сначала был один класс, а потом добавился второй. С самого начала было два класса, а необходимость связать их появилась гораздо позже, так что в первоначальном проекте их связь не была показана (за что и пострадал в конце концов). А метод хорош, только я бы сделал некий абстрактный интерфейс, и адаптировал бы к нему. Различия интерфейса спрятал бы в Visitor. Вот разве что дополнительные классы мне не очень нравятся, но за всё приходится платить. Спасибо за помощь, возможно совет пригодится в будущем
Записан
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines