Logo Море(!) аналитической информации!
IT-консалтинг Software Engineering Программирование СУБД Безопасность Internet Сети Операционные системы Hardware
Архив форумов ЦИТФорума
Море(!) вопросов - Море(!) ответов
 
 FAQFAQ   ПоискПоиск   ПользователиПользователи   ГруппыГруппы   РегистрацияРегистрация 
 ПрофильПрофиль   Войти и проверить личные сообщенияВойти и проверить личные сообщения   ВходВход 
Как правильно задавать вопросы

Паттерны 'абстрактная фабрика' и 'адаптер'

 
Перейти:  
Этот форум закрыт, вы не можете писать новые сообщения и редактировать старые.   Эта тема закрыта, вы не можете писать ответы и редактировать сообщения.    Список форумов Архив форумов ЦИТФорума -> Программирование
Предыдущая тема :: Следующая тема  
Автор Сообщение
af



Зарегистрирован: 18.12.2007
Сообщения: 1

СообщениеДобавлено: Вт Дек 18 2007 17:44    Заголовок сообщения: Паттерны 'абстрактная фабрика' и 'адаптер' Ответить с цитатой

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

Мне таки удалось написать компилирующийся код, но всё равно есть несколько вопросов
Код:

// ===== engwrp.h =====
class TSphere
{
public:
   virtual void display( float x, float y, float z, float size ) = 0;
};

class TEngineWrapper
{
public:
   virtual ~TEngineWrapper();
   virtual TSphere *obtainSphere( ) = 0;
   virtual void arrangeSphere( TSphere *sphere, float x, float y, float z, float size ) = 0;
};

TEngineWrapper *createIrrlichtWrapper();


// ===== engwrp.cpp =====
#include "engwrp.h"

#include <irrlicht.h>

class TIrrlichtWrapper;

class TIrrlichtSphere : public TSphere
{
   ISceneNode *node;
   friend class TIrrlichtWrapper;
public:
   TIrrlichtSphere( ISceneNode* _node );
   virtual void display( float x, float y, float z, float size );
};

class TIrrlichtWrapper : public TEngineWrapper
{
   IrrlichtDevice *device;
   IVideoDriver *driver;
   ISceneManager *sceneManager;
   IGUIEnvironment *guiEnv;
public:
   TIrrlichtWrapper();
   virtual ~TIrrlichtWrapper();
   virtual TSphere *obtainSphere();
   virtual void arrangeSphere( TSphere *sphere, float x, float y, float z, float size );
};

TIrrlichtSphere::TIrrlichtSphere( ISceneNode *_node )
{
   node = _node;
}

TIrrlichtWrapper::TIrrlichtWrapper()
{
   device = createDevice( EDT_DIRECT3D9, dimension2d<s32>( 640, 480 ), 16 );
   driver = device->getVideoDriver();
   sceneManager = device->getSceneManager();
   guiEnv = device->getGUIEnvironment();
}

TIrrlichtWrapper::~TIrrlichtWrapper()
{
   device->drop();
}

TSphere *TIrrlichtWrapper::obtainSphere()
{
   return new TIrrlichtSphere( sceneManager->addSphereSceneNode( ) );
}
void TIrrlichtWrapper::arrangeSphere( TSphere *sphere, float x, float y, float z, float size )
{
   /*1*/
   ( ( TIrrlichtSphere* )appearence )->node->setPosition( vector3df( x, y, z ) );
   ( ( TIrrlichtSphere* )appearence )->node->setScale( vector3df( size, size, size ) );
}
TEngineWrapper *createIrrlichtWrapper()
{
   return new TIrrlichtWrapper;
}


Теперь вопросы:
1) подскажите, как лучше сделать, разбить весь код на большое количество модулей (engwrp.h, engwrp.cpp, irrwrp.h, irrwrp.cpp (xors3d.h, xors3d.cpp, если буду впоследствии использовать движок xors3d) ) или оставить всё в двух файлах (engwrp.h и engwrp.cpp)?
2) в правильных ли местах описана и определена функция createIrrlicheWrapper?
3) самое главное про интерфейс TSphere и его реализацию TIrrlichtSphere. Как-то с ним полностью красиво не получается.
Например в /*1*/ приходится явно приводить тип к классу-наследнику, потому что, если описать функцию
Код:
void TIrrlichtWrapper::arrangeSphere( TIrrlichtSphere *sphere, float x, float y, float z, float size );

то компилятор не зачтёт эту функцию за реализацию чисто виртуальной
Код:
void TEngineWrapper::arrangeSphere( TSphere *sphere, float x, float y, float z, float size );

и не разрешит создать экземпляр абстрактного класса TIrrlichtWrapper.
Правильный ли вообще подход - описывать его отдельным от TEngineWrapper классом? Я пытался сделать TEngineWrapper шаблонным классом и передавать TSphere в качестве параметра, но при таком подходе явное обращение к TIrrlichtSphere вылазило в основную программу.
Вернуться к началу
Посмотреть профиль Отправить личное сообщение
tellary



Зарегистрирован: 29.01.2008
Сообщения: 7

СообщениеДобавлено: Вт Янв 29 2008 11:22    Заголовок сообщения: Ответить с цитатой

1) Лучше: отдельные файлы на каждый новую имплементацию.

2) createIrrlecheWrapper не нужна вообще (либо должна быть объявлена в irrwrp.h), т.к. использование TEngineWrapper (и всего что с ним связно) будет идти в два шага:
а) создание конкретной имплементации
б) передача указателя TEngineWrapper* коду, который его будет использовать.
Код, из п. (б) будет знать только об интерфейсе, код из п. (а) будет знать о конкретной имплементации, которую создает, а посему может создать конкретный "энджин" оператором new, либо воспользоваться create-функцией объявленной в irrwrp.h. Если же оставить этот метод в engwrp.h, то для каждой новой имплементации придется модифицировать этот хедер.

3) Не понятно почему arrangeSpehere это метод движка, а не самой сферы. Если бы это был метод сферы, то проблемы с кастом не было бы, т.к. конкретный экземпляр сферы при вызове arrange знал бы к какой библиотеке обращаться (irrlicht или другая).
Если же оставить все как есть, то в принципе каст - это приемлемо.

"пытался сделать TEngineWrapper шаблонным классом и передавать TSphere в качестве параметра, но при таком подходе явное обращение к TIrrlichtSphere вылазило в основную программу." - как вариант: сделать клиентский код тоже шаблонным.



И немножко о вкусном:
1. В данном случае TEngineWrapper это не адаптер, а фасад.
2. Нужно подумать зачем вообще методы манипуляции со сверой оказались в фасаде движка, а не в самой сфере? Следуя этой идеологии можно и метод display вынести в "движок", а вместо TSphere-указателя в вызове obtainSpehere возвращать int в качестве handler'a на конкретную сферу. Может не стоит смешивать эти два подхода?
Вернуться к началу
Посмотреть профиль Отправить личное сообщение
Показать сообщения:   
Этот форум закрыт, вы не можете писать новые сообщения и редактировать старые.   Эта тема закрыта, вы не можете писать ответы и редактировать сообщения.    Список форумов Архив форумов ЦИТФорума -> Программирование Часовой пояс: GMT + 3
Страница 1 из 1

 
Перейти:  
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах


Powered by phpBB © 2001, 2002 phpBB Group
Русская поддержка phpBB

 

IT-консалтинг Software Engineering Программирование СУБД Безопасность Internet Сети Операционные системы Hardware

Информация для рекламодателей PR-акции, размещение рекламы — adv@citforum.ru,
тел. +7 495 6608306, ICQ 232284597
Пресс-релизы — pr@citforum.ru
Послать комментарий
Информация для авторов
This Web server launched on February 24, 1997
Copyright © 1997-2000 CIT, © 2001-2006 CIT Forum
Внимание! Любой из материалов, опубликованных на этом сервере, не может быть воспроизведен в какой бы то ни было форме и какими бы то ни было средствами без письменного разрешения владельцев авторских прав. Подробнее...