Как объединить автоматический метод получения и установки с шаблоном проектирования PIMPL в классе интерфейса общедоступного API - PullRequest
0 голосов
/ 09 декабря 2011
//////////////////////////////////////////////////////////////////////////////////////////
// Note: Automatically generate getter and setter
template<typename T>
class Wrap {
public:
  ...
  const T& operator()() const 
  { 
    return m_element; 
  }

  void operator()(const T& element)
  {
    m_element = element;
  }
  ...

private:
  T m_element;
};

// Pro:  The container may have more than 20 different member variables.
//       Each goes with a simple getter and setter for now. Due to the Wrap
//       class, we don't have to add getter and setter for any new variable
// Con:  Since this is a public API interface, if the user directly adopt the
//       Wrap class, it is difficult for any future improvement. Based on this design,
//       we cannot make Wrap private embeded class of Container since the user needs to 
//       access those public member variables of Container
class Container
{
public:
  Wrap<int>         Age;
  Wrap<double>      Balance;
  ...
};

//////////////////////////////////////////////////////////////////////////////////////////
// Con: For each different member variable, we have to add getter and setter methods
//       which will be a problem considering if you have 20 member variables.
// Pro:
//       By using PIMPL pattern, we can make the interface more robust for future improvement
//       without breaking our client's code.
class PimplClass
{
public:
    int Age() const;
    PimplClass& Age(int _age);

    double Balance() const;
    PimplClass& Balance(double _balance);

private:
    Pimpl* m_data; // hide internal data structure from the public API interface
};
//////////////////////////////////////////////////////////////////////////////////////////

Вопрос > Есть ли лучший дизайн, в котором я могу комбинировать как автоматическое получение + создание сеттера, так и шаблон проектирования PIMPL в этот публичный интерфейс API?

Спасибо

// ****** Обновлено ***** *******

Прочитав все эти статьи, я убежден, что добытчик и установщик - зло. Теперь возникает вопрос, как избежать их всех вместе.

Например,

class Bond
{
    ...

private:
    long m_lPrice;
    std::string m_strBondName;
    int  m_iVolume;
}

Дайте вышеуказанный класс Bond, который включает в себя три переменные-члены, без использования getter и setter, как клиент получает цену, имя или объем объекта облигации?

Это еще один пример получения / установки в Qt4.

Вот улучшенный API QProgressBar:

class QProgressBar : public QWidget
{
    ...
public:
    void setMinimum(int minimum);
    int minimum() const;
    void setMaximum(int maximum);
    int maximum() const;
    void setRange(int minimum, int maximum);
    int value() const;

    virtual QString text() const;
    void setTextVisible(bool visible);
    bool isTextVisible() const;
    Qt::Alignment alignment() const;
    void setAlignment(Qt::Alignment alignment);

public slots:
    void reset();
    void setValue(int value);

signals:
    void valueChanged(int value);
    ...
};

Спасибо

1 Ответ

8 голосов
/ 10 декабря 2011

Есть геттеры и сеттеры, так что вы можете «схватить» кишки объекта и возиться с его внутренностями.Это должно сделать ваши звонки очень громко.Для хорошо спроектированного класса вам не нужно копаться в его кишках, поскольку он позволяет вам делать все, что вам нужно сделать через его интерфейс без утечки каких-либо подробностей его реализации через абстракцию.

Разработка класса с точки зрения пользователя класса ( ", еслиУ меня есть qrxl объект, мне нужно было бы сделать его wrgl() таким, и мне также нужно время от времени передавать ему lrxl объект, который он затем использует для выполнения frgl() "), скореечем с точки зрения реализатора , которому нужно каким-то образом организовать свои данные и алгоритмы в полезные (для него!) куски.( «Давайте просто поместим этого Джонни сюда в тот класс, потому что именно там он находится близко к тому месту, где он мне нужен для реализации алгоритма xrxl())

Я думаю, что в этомВ отношении Java оказала огромную медвежью услугу человечеству в том смысле, что требует , чтобы вы поместили все в некоторый класс, даже если это противкак вы на самом деле визуализируете свой дизайн в своей голове, и даже если вы (еще) не думаете об объектно-ориентированном мышлении.Это, кажется, сделало стиль дизайна модным, когда программисты просто помещают все в какой-то класс, потому что «это так».
Во многих кодах Java, которые я видел, базовый стиль программирования на самом деле СтруктурированныйПрограммирование (в основном "собирать ваши данные в полезные куски и передавать их в ваши алгоритмы", как это делается на C или Pascal), а не Объектно-ориентированное программирование .То, что вы заменяете struct / record на class и делаете элементы данных в этом чанке доступными только через методы получения и установки, это не означает, что вы занимаетесь объектно-ориентированным программированием. 1 Это то, что автор этой замечательной короткой статьи называет псевдоклассами

Из того, что я мало знаю о Qt, его дизайн такжедовольно хороший пример для довольно плохого примера, со всем, что распределено в куче, передано голыми указателями и с использованием квазиклассной школы дизайна.


Дайте вышеуказанный класс Bond, который включает в себя три переменные-члены, без использования getter и setter, как клиент получает цену, имя или объем объекта облигации?

Это неправильный вопрос .Правильный вопрос: зачем пользователю получать эти значения? Если вам нужно получить их вручную, тогда Bond недостаточно высокая абстракция для разработки ОО.Это простой C-стиль struct, где вы собираете все необходимые данные в одном месте.Задайте себе вопрос:

Что бы пользователь Bond хотел сделать с таким объектом? Как я могу заставить класс поддерживать эти операции, не имея пользователейсхватиться за него и возиться с его кишками?Как я могу заставить классы, которые взаимодействуют с Bond, делать это?Могу ли я передать им Bond объектов, а не цену, имя или объем объекта облигации?

Да, иногда вам просто нужна цена облигации, чтобы отобразить ее, и если это тактогда Bond нужно будет поддерживать функцию получения цены, и тогда все в порядке.Но вы все равно можете передать объект Bond в вашу функцию BondPriceTable displayBonds(), и пусть он решит, хочет ли он просто взять имя и цену и выбросить их на экран или отобразить больше значений.Нет необходимости извлекать имя и цену вручную и передавать их в функцию display().


1 Это особенно ужасно, потому что поклонники Java так часто смотрят на C ++ за то, что они не "чисто OO".

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...