這次介紹的 Private class data 模式可以說的上是 Qt/KDE 裡最常見的設計模式了,Private class data 模式又叫 PIMPL (Private IMPLementation) ,Opaque pointer,handle/body 或 cheshire cat,該模式把類屬性包裝到獨立的資料物件中來最小化資料的可見性,以避免在物件構建後對資料誤操作。該模式在 Qt/KDE 稱為 D-Pointers,不僅起到了包裝類屬性的作用,而且很好地解決了二進位相容性的問題。先看下面一段代碼:
- 代碼: 選擇全部
view source
print?
class KoShapeShadow::Private
{
public:
Private()
: offset(0, 0), color(Qt::black), blur(8), visible(true), refCount(0) {
}
QPointF offset;
QColor color;
qreal blur;
bool visible;
QAtomicInt refCount;
};
KoShapeShadow::KoShapeShadow()
: d(new Private())
{
}
KoShapeShadow::~KoShapeShadow()
{
delete d;
}
void KoShapeShadow::fillStyle(KoGenStyle &style, KoShapeSavingContext &context)
{
Q_UNUSED(context);
style.addProperty("draw:shadow", d->visible ? "visible" : "hidden");
style.addProperty("draw:shadow-color", d->color.name());
if (d->color.alphaF() != 1.0)
style.addProperty("draw:shadow-opacity", QString("%1%").arg(d->color.alphaF() * 100.0));
style.addProperty("draw:shadow-offset-x", QString("%1pt").arg(d->offset.x()));
style.addProperty("draw:shadow-offset-y", QString("%1pt").arg(d->offset.y()));
if (d->blur != 0)
style.addProperty("koffice:shadow-blur-radius", QString("%1").arg(d->blur));
}
非 常簡單的一種設計模式。建立一個 Private 類用於存儲所有資料,Private 類的構造函數初始化所有 KoShapeShadow 類的資料的值,構造 KoShapeShadow 時新建一個 Private 物件賦給指標 d,這樣需要調用 KoShapeShadow 物件的資料時使用 d->xx 就可以了。
D- Pointers在 Qt 庫,kdelibs 和 Calligra-libs 中應用非常廣泛,但它們最主要的功能並不是最小化資料的可見性,它們是為了保證二進位相容性。什麼是二進位相容性呢?如果一個庫升級了,原來動態連結到該 庫的應用程式不需要重新編譯即可連結到新的二進位版本,這個庫就是二進位相容的。否則如果應用程式需要重編譯(但不需要修改)這個庫就是源碼相容的。二進 制相容性保證了每次系統裡的 Qt 包升級後不用把所有 Qt 程式也更新一遍。如果沒有 D-Pointers,由於所有的成員變數直接寫在類定義裡,新增成員變數後各變數在新的庫檔中的位址就可能發生變化,應用程式和庫檔的位址映射就不對應了,而使用 D-Pointers 之後,應用程式只知道庫檔有一個叫 d 的指標,d 的位址是不變的。
參考閱讀:
http://techbase.kde.org/Policies/Librar ... D-Pointers
http://techbase.kde.org/index.php?title ... th_C%2B%2B
http://philacorns.wordpress.com/2011/01 ... %E5%BC%8F/