在公共API接口类中如何将自动吸气装置与PIMPL设计模式相结合 [英] How to combine auto getter&setter with PIMPL design pattern in a public API interface class

查看:298
本文介绍了在公共API接口类中如何将自动吸气装置与PIMPL设计模式相结合的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  ////////////////////////////////////// ////////////////////////////////////////////////// // 
//注意:自动生成getter和setter
template< typename T>
class Wrap {
public:
...
const T& operator()()const
{
return m_element;
}

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

私人:
T m_element;
};

// Pro:容器可能有20多个不同的成员变量。
//每个都有一个简单的getter和setter现在。由于Wrap
//类,我们不必为任何新变量
// Con添加getter和setter:由于这是一个公共API接口,如果用户直接采用
//包装类,今后的改进是很困难的。基于这个设计,
//我们不能使用Wrap私有嵌入的Container类,因为用户需要
//访问Container的
class Container
{
public:
Wrap< int>年龄;
包裹< double>平衡;
...
};

//////////////////////////////////////// ////////////////////////////// $ b // Con:对于每个不同的成员变量,我们必须添加getter和setter方法
//这将是一个问题,考虑到如果你有20个成员变量。
// Pro:
//通过使用PIMPL模式,我们可以使界面更加健壮,以便将来改进
//,而不会破坏客户端的代码。
class PimplClass
{
public:
int Age()const;
PimplClass&年龄(int _age);

double Balance()const;
PimplClass&平衡(双重平衡);

private:
Pimpl * m_data; //从公共API接口
}隐藏内部数据结构;
////////////////////////////////////////// ////////////////////////////
code>

问题>是否有更好的设计,我可以结合自动getter + setter生成和PIMPL设计模式
到这个公共API接口?



谢谢



// > * ** * ** 已更新 * ** * ** ** * **



阅读所有这些文章后,我相信getter和setter是邪恶的。现在问题是如何避免他们在一起。



例如,

  class Bond 
{
...

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

给上述类债券其中包括三个成员变量,不使用getter和setter,客户如何获得债券对象的价格,名称或体积?



这是另一个例子在Qt4中的getter / setter。



这是改进的QProgressBar API:

  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 ::对齐对齐()const;
void setAlignment(Qt :: Alignment alignment);

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

信号:
void valueChanged(int value);
...
};

谢谢

解决方案< 。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。这应该让你的闹钟响起来很响亮。对于 精心设计的课程 ,您不需要挖掘其内心,因为它可以让您通过其界面执行所需的所有功能 而不会通过抽象泄漏其实现细节



用户的角度设计 类(如果我有一个 qrxl 对象,我需要使它 wrgl()这样,我也需要偶尔传递一个 lrxl 对象,然后用它来执行 frgl()),而不是从实施者的角度来看,他们需要以某种方式将他的数据和算法组织成有用的(对他而言)的块。 (让我们把这个Johnny放在这个课上,因为这是我需要它来实现 xrxl()算法的地方。



我认为在这方面,Java对人类造成了巨大的不满, ,因为它 需要 将所有内容都放入课堂,即使这与您的头脑中实际可视化您的设计有关,即使您尚未思考面向对象。这似乎已经使设计风格变得流行,程序员只需将所有内容都放到某个类中,因为这是完成的方式。

在许多Java代码中,我看到底层编程风格实际上是结构化编程(基本上是以有用的块收集数据,并将其传递给您的算法,如C或Pascal所述),而不是面向对象编程。只是因为你用 class 替换 struct / record 这个块中的数据成员只能通过getter和setter访问,这并不意味着你正在进行面向对象的编程。 1 这是那美妙的短文调用 伪类



从关于Qt的小知识,它的设计也是一个非常好的例子,一个非常糟糕的例子,一切分配在堆上,用裸指针传递,并采用准班设计。







给上述类债券其中包含三个成员变量,而不使用getter和setter,客户如何获取债券对象的价格,名称或数量?


这是 错误的问题 。正确的问题是 为什么用户需要获得这些值? 如果您需要手动获取,那么债券对于OO设计来说,抽象不够高,它只是一个C风格的 struct ,您可以将所有需要的数据放在一起。问问自己:



Bond 的用户想要这样做对象? 如何让类支持这些操作,而无需用户抓住它并消除其胆量?如何使与 Bond 交互的类执行此操作?我可以通过他们 c> Bond 对象,而不是债券对象的价格,名称或数量?



是的,有时你必须要有一个债券的价格来显示它,如果是这样的话,那么 Bond 将需要支持一个getter函数的价格,那就OK了然后。但您仍然可以将 Bond 对象传递给您的 BondPriceTable displayBonds()函数,并且让它决定是否只是抓住名称和价格,并抛出在屏幕上或显示更多的值。不需要手动提取名称和价格,并将它们传递给 display()函数。






1 这是特别令人震惊的,因为Java爱好者经常看不起在C ++中不是纯粹的OO。


//////////////////////////////////////////////////////////////////////////////////////////
// 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
};
//////////////////////////////////////////////////////////////////////////////////////////

Question> Is there a better design that I can combine both auto getter+setter generation and PIMPL design pattern into this public API interface?

Thank you

// ****** Updated ************

After reading all those articles, I am convinced that getter and setter are evil. Now the question comes to how to avoid them all together.

For example,

class Bond
{
    ...

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

Give the above class Bond which includes three member variables, without using getter and setter, how does client get the price, name, or volume of an bond object?

This is the another example of getter/setter in Qt4.

Here's the improved QProgressBar API:

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);
    ...
};

Thank you

解决方案

Getters and setters are there so that you can "grab" into an object's guts and fiddle with its innards. That should make your alarm bells ring very loudly. For a well-designed class, you do not have to dig through its guts, since it lets you do everything you need to do through its interface without leaking any of its implementation details through the abstraction.

Design a class from the point of view of a user of the class ("if I have a qrxl object, I would need to make it wrgl() like this, and I also need to pass it a lrxl object occasionally, which it then uses to do frgl()"), rather than from the point of view of the implementer who needs to somehow organize his data and algorithms into useful (for him!) chunks. ("Let's just put this Johnny over here into that class, because that's where it is close to where I need it for implementing the xrxl() algorithm.")

I think in this regard Java has done a huge disservice to humanity in that it requires you to put everything into some class, even if this is against how you actually visualize your design in your head, and even if you are not (yet) thinking object-oriented. This seems to have made a design style en vogue where programmers just stuff everything into some class somewhere because "that's the way it's done."
In lots of Java code I've seen the underlying programming style is actually Structured Programming (basically "collect your data in useful chunks, and pass those to your algorithms", as done in C or Pascal), rather than Object-oriented Programming. Just because you replace struct/record by class and make the data members in this chunk only accessible through getters and setters, this doesn't mean you are doing object-oriented programming.1 This is what the author of that wonderful short paper calls pseudo classes

From what little I know about Qt, its design is also a pretty good example for a pretty bad example, with everything allocated on the heap, handed around in naked pointers, and employing the quasi-class school of design.


Give the above class Bond which includes three member variables, without using getter and setter, how does client get the price, name, or volume of an bond object?

This is the wrong question. The right question is why would a user need to get at those values? If you need to get at them manually, then Bond isn't high enough an abstraction for OO design, it's a mere C-style struct where you throw together all the data you need in one place. Ask yourself:

What would a user of a Bond want to do with such an object? How can I make the class support those operations without users having to grab into it and fiddle with its guts? How can I make the classes that interact with Bond do this? Can I pass them Bond objects, rather than price, name, or volume of an bond object?

Yes, sometimes you have to have just a bond's price in order to display it, and if that's the case, then Bond will need to support a getter function for the price, and that's Ok then. But you could still pass a Bond object to your BondPriceTable's displayBonds() function, and let that decide whether it wants to just grab the name and the price and throw that at the screen or display more values. There is no need to extract name and price manually and pass those to a display() function.


1 That's especially appalling because Java aficionados so often look down at C++ for not being "purely OO".

这篇关于在公共API接口类中如何将自动吸气装置与PIMPL设计模式相结合的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆