Класс с двумя интерфейсами, как лучше реализовать?
От: Андрей Е  
Дата: 24.06.11 09:48
Оценка:
Есть класс, реализующий некоторую функциональность. У него должно быть два публичных интерфейса — один для "чужих" и другой для "своих". Причем, нужно чтобы чужие не имели доступа к интерфейсу для своих. И желательно вообще, чтобы они не знали о существовании этого интерфейса. Однако нужно, чтобы чужие могли создавать экземпляры этого класса.

Чтобы стало понятней, поясню на примере:
class Window
{
public: //Интерфейс для чужих
  Window(); //Чужие могут создавать экземпляры этого класса
  void SetSize(int x, int y); //Чужие могут выполнять какие-то действия с этим классом

public: //Интерфейс для своих, должен быть недоступен для чужих
  HWND GetHwnd(); //Чужим не обязательно знать, что используется именно такой способ реализации этого объекта.
};


Как это можно сделать проще всего и как можно более естественно?

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

Может быть есть какая-нибудь готовая идиома или паттерн проектирования реализующие такую схему?
c++ интерфейсы
Re: Класс с двумя интерфейсами, как лучше реализовать?
От: vayerx  
Дата: 24.06.11 10:29
Оценка: 1 (1)
Здравствуйте, Андрей Е, Вы писали:

АЕ>Есть класс, реализующий некоторую функциональность. У него должно быть два публичных интерфейса — один для "чужих" и другой для "своих". Причем, нужно чтобы чужие не имели доступа к интерфейсу для своих. И желательно вообще, чтобы они не знали о существовании этого интерфейса. Однако нужно, чтобы чужие могли создавать экземпляры этого класса.

АЕ>Как это можно сделать проще всего и как можно более естественно?
АЕ>Допустимо создавать вспомогательные классы и использовать наследование.
АЕ>Дружбу использовать не желательно(по крайней мере дружбу со всеми своими), так как список своих заранее не известен, и к тому же не всем своим следует иметь доступ к внутренним деталям реализации этого класса. Дружба со вспомогательным классами допустима.

АЕ>Может быть есть какая-нибудь готовая идиома или паттерн проектирования реализующие такую схему?


// реализация через виртуальный интерфейс
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);             // релизация
};

//-------------------------------------------------------------------------------------------------------------
// реализация через PIMPL
class 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: Класс с двумя интерфейсами, как лучше реализовать?
От: jyuyjiyuijyu  
Дата: 24.06.11 10:34
Оценка:
Здравствуйте, Андрей Е, Вы писали:

мне хотелось похожего я читал у Страуструпа но он там приводил пример с пространствами имен и просто Plain C интерфейсом типа в пространство имен для клиентов будет чистый интерфейс а для разработчиков со всеми спомогательными функциями по сути это два заголовочных файла для клиента "чистый" и для разработчика "грязный" но мне надо было тоже для класса так как сильно много торчало того что нужно знать только разработчику в клиентском "чистом" интерфейсе я пока вижу только одно решение Pimpl прячем там все для разработчика "грязные функции" + "какие то данные" минус это лишняя косвенность и каждый раз выделять в куче место я еще пробовал два объявления класса один для клиентов другой для разработчиков (не добавляя данные просто прятал интерфейс грязный) но это какой то хак омерзительный я от него отказался хотя в Plain C именно так и делают два определения типа "чистый" и "грязный" но там скрывают данные вот пример в C проблем нет с доступом поэтому ненадо в интерфейс тащить детали реализации (функции которым нужен приватный доступ) а вот в C++ надо как минимум там написать friend но это нехочется видеть и знать про это это реализация в C++ наверное только Pimpl хотя кто знает может и еще как то можно
garray.h
struct _GArray
{
  gchar *data;
  guint len;
};

garray.c
struct _GRealArray
{
  guint8 *data;
  guint   len;
  guint   alloc;
  guint   elt_size;
  guint   zero_terminated : 1;
  guint   clear : 1;
};
GArray*
g_array_append_vals (GArray       *farray,
             gconstpointer data,
             guint         len)
{
  GRealArray *array = (GRealArray*) farray;
Re: Класс с двумя интерфейсами, как лучше реализовать?
От: Erop Россия  
Дата: 24.06.11 14:41
Оценка:
Здравствуйте, Андрей Е, Вы писали:

АЕ>Может быть есть какая-нибудь готовая идиома или паттерн проектирования реализующие такую схему?


Ну, например, я знаю успешный пример применения такой схемы. У нас есть какой-то токен, доступ к которому имеют только свои (например оно не экспортируется наружу из чего-то), и для доступа к интерфейсу "для своих", нужно предъявить этот токен...

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: Класс с двумя интерфейсами, как лучше реализовать?
От: Ryadovoy  
Дата: 26.06.11 06:30
Оценка: +1
Здравствуйте, Андрей Е, Вы писали:
АЕ>Может быть есть какая-нибудь готовая идиома или паттерн проектирования реализующие такую схему?

Ко всем ответам хотелось бы добавить еще и COM,
в классах которого может быть сколько угодно не связанных интерфейсов, получаемых через QueryInterface
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.