Есть класс, реализующий некоторую функциональность. У него должно быть два публичных интерфейса — один для "чужих" и другой для "своих". Причем, нужно чтобы чужие не имели доступа к интерфейсу для своих. И желательно вообще, чтобы они не знали о существовании этого интерфейса. Однако нужно, чтобы чужие могли создавать экземпляры этого класса.
Чтобы стало понятней, поясню на примере:
class Window
{
public: //Интерфейс для чужих
Window(); //Чужие могут создавать экземпляры этого классаvoid SetSize(int x, int y); //Чужие могут выполнять какие-то действия с этим классомpublic: //Интерфейс для своих, должен быть недоступен для чужих
HWND GetHwnd(); //Чужим не обязательно знать, что используется именно такой способ реализации этого объекта.
};
Как это можно сделать проще всего и как можно более естественно?
Допустимо создавать вспомогательные классы и использовать наследование.
Дружбу использовать не желательно(по крайней мере дружбу со всеми своими), так как список своих заранее не известен, и к тому же не всем своим следует иметь доступ к внутренним деталям реализации этого класса. Дружба со вспомогательным классами допустима.
Может быть есть какая-нибудь готовая идиома или паттерн проектирования реализующие такую схему?
Здравствуйте, Андрей Е, Вы писали:
АЕ>Есть класс, реализующий некоторую функциональность. У него должно быть два публичных интерфейса — один для "чужих" и другой для "своих". Причем, нужно чтобы чужие не имели доступа к интерфейсу для своих. И желательно вообще, чтобы они не знали о существовании этого интерфейса. Однако нужно, чтобы чужие могли создавать экземпляры этого класса. АЕ>Как это можно сделать проще всего и как можно более естественно? АЕ>Допустимо создавать вспомогательные классы и использовать наследование. АЕ>Дружбу использовать не желательно(по крайней мере дружбу со всеми своими), так как список своих заранее не известен, и к тому же не всем своим следует иметь доступ к внутренним деталям реализации этого класса. Дружба со вспомогательным классами допустима.
АЕ>Может быть есть какая-нибудь готовая идиома или паттерн проектирования реализующие такую схему?
// реализация через виртуальный интерфейсclass IPublicWindow {
public:
virtual ~IPublicWindow();
static std::auto_ptr<IPublicWindow> Create();
virtual void SetSize(int x, int y) = 0; //Чужие могут выполнять какие-то действия с этим классом
};
std::auto_ptr<IPublicWindow> IPublicWindow::Create() { return new PrivateWindow; }
class PrivateWindow : public IPublicWindow {
public:
HWND GetHwnd(); //Чужим не обязательно знать, что используется именно такой способ реализации этого объекта.void SetSize(int x, int y); // релизация
};
//-------------------------------------------------------------------------------------------------------------
// реализация через PIMPLclass PublicWindow {
public:
PublicWindow();
~PublicWindow();
void SetSize(int x, int y); //Чужие могут выполнять какие-то действия с этим классомprivate:
PublicWindow(const PublicWindow &); // копирование и присваивание, в принципе, можно реализоватьclass PrivateWindow *pImpl;
};
// практически то же самое, что и в случае с виртуальным интерфейсом, но наследование заменено косвенным вызовомclass PrivateWindow {
public:
HWND GetHwnd(); //Чужим не обязательно знать, что используется именно такой способ реализации этого объекта.void SetSize(int x, int y); // релизация
}
PublicWindow::PublicWindow() : pImpl(new PrivateWindow) {}
void PublicWindow::SetSize(int x, int y) { pImpl->SetSize(x, y); }
Re: Класс с двумя интерфейсами, как лучше реализовать?
мне хотелось похожего я читал у Страуструпа но он там приводил пример с пространствами имен и просто Plain C интерфейсом типа в пространство имен для клиентов будет чистый интерфейс а для разработчиков со всеми спомогательными функциями по сути это два заголовочных файла для клиента "чистый" и для разработчика "грязный" но мне надо было тоже для класса так как сильно много торчало того что нужно знать только разработчику в клиентском "чистом" интерфейсе я пока вижу только одно решение Pimpl прячем там все для разработчика "грязные функции" + "какие то данные" минус это лишняя косвенность и каждый раз выделять в куче место я еще пробовал два объявления класса один для клиентов другой для разработчиков (не добавляя данные просто прятал интерфейс грязный) но это какой то хак омерзительный я от него отказался хотя в Plain C именно так и делают два определения типа "чистый" и "грязный" но там скрывают данные вот пример в C проблем нет с доступом поэтому ненадо в интерфейс тащить детали реализации (функции которым нужен приватный доступ) а вот в C++ надо как минимум там написать friend но это нехочется видеть и знать про это это реализация в C++ наверное только Pimpl хотя кто знает может и еще как то можно
garray.h
Здравствуйте, Андрей Е, Вы писали:
АЕ>Может быть есть какая-нибудь готовая идиома или паттерн проектирования реализующие такую схему?
Ну, например, я знаю успешный пример применения такой схемы. У нас есть какой-то токен, доступ к которому имеют только свои (например оно не экспортируется наружу из чего-то), и для доступа к интерфейсу "для своих", нужно предъявить этот токен...
struct SecreetTokenType; // где-то есть SecreetTokenType SecreetToken;class SvojSrediChuzhikhChuzhojSrediSvoikh : private IForFriendsOnli {
public:
// тут интерфейс для всех
SvojSrediChuzhikhChuzhojSrediSvoikh() : forFriends( this ) {}
SvojSrediChuzhikhChuzhojSrediSvoikh( const SvojSrediChuzhikhChuzhojSrediSvoikh& other ) :
forFinends( this ) {}
SvojSrediChuzhikhChuzhojSrediSvoikh& operator = ( const SvojSrediChuzhikhChuzhojSrediSvoikh& other )
{ /*тут реализация, но forFriends не трогаем! */ }
// тут ещё чегой-тоclass ForFriendsOnly {
ForFriendsOnly( SvojSrediChuzhikhChuzhojSrediSvoikh* theMaster_ ) : theMaster( theMaster_ ) {}
public:
void Method1() { do somth with theMaster; }
void Method2() { do somth with theMaster; }
void Method3() { do somth with theMaster; }
}& ForFriends( const SecreetTokenType& );
private:
ForFriendsOnly forFriends;
}
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re: Класс с двумя интерфейсами, как лучше реализовать?