【更新】
2012-7-9,设计模式(5)-装饰模式(Decorator),运用装饰模式的版本
2012-6-18,添加实例下载地址,文章末尾
2012-6-8,更新示例代码
【描述】模板设计模式将常用的方法进行封装,创建了一个实施一组方法和功能的抽象的对象。子类通常将这个对象作为模板用于设计。
【UML图】
图1 UML图
1 DrawTemplate有三个抽象的方法:draw() - (protected)、getMethod() - (public)、setMethod() - (protected、纯虚函数-接口)
2 Draw1和Draw2继承了DrawTemplate,Draw1对draw()方法进行了重载、重用了DrawTemplate类的getMethod()方法,实现了setMethod接口。Draw2对draw()、getMethod()方法进行了重载,实现了setMethod接口。
3 对方法的重用是模板模式的优点,如Draw1重用了DrawTemplate类的getMethod方法
【示例代码】
drawtemplate.h
#ifndef DRAWTEMPLATE_H #define DRAWTEMPLATE_H #include <QString> class DrawTemplate { public: DrawTemplate(); protected: virtual void draw(); virtual void setMethod(QString method) const = 0; public: virtual QString getMethod(); }; #endif // DRAWTEMPLATE_H
drawtemplate.cpp
#include <QDebug> #include "drawtemplate.h" DrawTemplate::DrawTemplate() { qDebug()<<"construct DrawTemplate"; } void DrawTemplate::draw() { qDebug()<<"DrawTemplate::draw()"; setMethod(getMethod()); } QString DrawTemplate::getMethod() { QString test = "Method::DrawTemplate"; qDebug()<<"DrawTemplate::getMethod()"; return test; }
draw1.h
#ifndef DRAW1_H #define DRAW1_H #include "drawtemplate.h" class Draw1 : public DrawTemplate { public: Draw1(); public: void draw(); void setMethod(QString) const; }; #endif // DRAW1_H
draw1.cpp
#include <QDebug> #include "draw1.h" Draw1::Draw1() { qDebug()<<"construct Draw1"; } void Draw1::draw() { qDebug()<<"Draw1::draw()"; setMethod(getMethod()); } void Draw1::setMethod(QString method) const { qDebug()<<QString("Draw1::setMethod(%1)").arg(method); }
draw2.h
#ifndef DRAW2_H #define DRAW2_H #include "drawtemplate.h" class Draw2 : public DrawTemplate { public: Draw2(); public: void draw(); QString getMethod(); void setMethod(QString method) const; }; #endif // DRAW2_H
draw2.cpp
#include <QDebug> #include "draw2.h" Draw2::Draw2() { qDebug()<<"construct Draw2"; } void Draw2::draw() { qDebug()<<"Draw2::draw()"; setMethod(getMethod()); } QString Draw2::getMethod() { QString test = "Method::Draw2"; qDebug()<<"Draw2::getMethod()"; return test; } void Draw2::setMethod(QString method) const { qDebug()<<QString("Draw2::setMethod(%1)").arg(method); }
main.cpp
#include "drawtemplate.h" #include "draw1.h" #include "draw2.h" int main(void) { Draw1 draw1; draw1.draw(); Draw2 draw2; draw2.draw(); }
【运行结果】
construct DrawTemplate construct Draw1 Draw1::draw() DrawTemplate::getMethod() "Draw1::setMethod(Method::DrawTemplate)" construct DrawTemplate construct Draw2 Draw2::draw() Draw2::getMethod() "Draw2::setMethod(Method::Draw2)"
【实例剖析】
*该实例不是严格的模板模式,因为并没有覆盖模板中的方法。有好的见解,欢迎留言!(2012-09-06)
Qt输入法设计(嵌入式)一文中介绍了一种输入法的设计,在使用时,需要对控件对象的名称进行指定,并对每个QLineEdit对象绑定输入法对象。能否有一种方法,使得编辑框自带输入法对象?
下面利用模板模式,将QLineEdit作为模板,派生一个QLineEditWithIM,使得QLineEditWithIM自带输入法,使用就像QLineEdit一样简单。UML图如图2所示:
图2
【代码清单】
仅贴出改动的部分,省略了keyboard.h、keyboard.cpp代码。详请参考Qt输入法设计(嵌入式)
inputmethod.h
#ifndef INPUTMETHOD_H #define INPUTMETHOD_H #include "keyboard.h" class InputMethod : public KeyBoard { Q_OBJECT public: InputMethod(); ~InputMethod(); bool eventFilter(QObject *obj, QEvent *event); public: KeyBoard *keyboard; public: void showKeyBoard(); }; #endif // INPUTMETHOD_H
inputmethod.cpp
#include <QDebug> #include "inputmethod.h" InputMethod::InputMethod() { keyboard = new KeyBoard; setWindowFlags(Qt::Tool|Qt::WindowStaysOnTopHint|Qt::FramelessWindowHint); } InputMethod::~InputMethod() { delete keyboard; } /* * Name : void eventFilter(QObject *obj, QEvent *event); * Type : QEvent * Func : judge input method event * In : QObject,QEvent * Out : bool */ bool InputMethod::eventFilter(QObject *obj, QEvent *event) { if(event->type()==QEvent::MouseButtonPress) { showKeyBoard(); return true; } return QObject::eventFilter(obj,event); } /* * Name : void showKeyBoard(); * Type : function * Func : show keyBoard * In : Null * Out : Null */ void InputMethod::showKeyBoard() { keyboard->setWindowFlags(Qt::Tool|Qt::WindowStaysOnTopHint|Qt::FramelessWindowHint); keyboard->move(50,120); keyboard->exec(); }
qlineeditwithim.h
#ifndef QLINEEDITWITHIM_H #define QLINEEDITWITHIM_H #include <QLineEdit> #include "inputmethod.h" class QLineEditWithIM : public QLineEdit { public: QLineEditWithIM(); private: InputMethod *im; }; #endif // QLINEEDITWITHIM_H
qlineeditwithim.cpp
#include "qlineeditwithim.h" QLineEditWithIM::QLineEditWithIM() { //#ifdef Q_WS_QWS im = new InputMethod; installEventFilter(im); connect(im->keyboard,SIGNAL(setvalue(QString)),this,SLOT(setText(QString))); //#endif }
login.h
#ifndef LOGIN_H #define LOGIN_H #include <QDialog> #include "qlineeditwithim.h" class QLabel; class QLineEdit; class QDialogButtonBox; class QLogin : public QDialog { Q_OBJECT public: QLogin(); ~QLogin(); public: QLabel *managerLabel; QLabel *passwdLabel; QLineEditWithIM *managerEdit; QLineEditWithIM *passwdEdit; QPushButton *okButton; QPushButton *cancelButton; QDialogButtonBox *buttonBox; signals: void Authorize(); private slots: void login(); void cancel(); }; #endif // LOGIN_H
login.cpp
#include <QtGui> #include "login.h" QLogin::QLogin() { managerLabel = new QLabel(tr("&Manager:")); managerEdit = new QLineEditWithIM(); managerLabel->setBuddy(managerEdit); passwdLabel = new QLabel(tr("&Passwd:")); passwdEdit = new QLineEditWithIM; passwdEdit->setEchoMode(QLineEdit::Password); passwdLabel->setBuddy(passwdEdit); okButton = new QPushButton(tr("&Login")); cancelButton = new QPushButton("&Cancel"); okButton->setDefault(true); buttonBox = new QDialogButtonBox; buttonBox->addButton(okButton, QDialogButtonBox::ActionRole); buttonBox->addButton(cancelButton, QDialogButtonBox::AcceptRole); connect(okButton, SIGNAL(clicked()), this, SLOT(login())); connect(cancelButton, SIGNAL(clicked()), this, SLOT(cancel())); QHBoxLayout *topLayout = new QHBoxLayout; topLayout->addWidget(managerLabel); topLayout->addWidget(managerEdit); QHBoxLayout *midLayout = new QHBoxLayout; midLayout->addWidget(passwdLabel); midLayout->addWidget(passwdEdit); QVBoxLayout *mainLayout = new QVBoxLayout; mainLayout->addLayout(topLayout); mainLayout->addLayout(midLayout); mainLayout->addWidget(buttonBox); mainLayout->setMargin(20); setLayout(mainLayout); managerEdit->setFocus(); QIcon icon; icon.addFile(QString::fromUtf8(":/new/main/picture/logo.png"), QSize(), QIcon::Normal, QIcon::Off); setWindowIcon(icon); setWindowTitle("Login"); } QLogin::~QLogin() { //qDebug()<<"login close"; delete managerLabel; delete managerEdit; delete passwdLabel; delete passwdEdit; delete okButton; delete cancelButton; } /* * Name : void login() * Type : slot * Func : login when authorize * In : Null * Out : Null */ void QLogin::login() { qDebug()<<managerEdit->text(); qDebug()<<passwdEdit->text(); } /* * Name : void cancel() * Type : slot * Func : cancel login * In : Null * Out : Null */ void QLogin::cancel() { managerEdit->clear(); passwdEdit->clear(); close(); }
main.cpp
#include <QtGui/QApplication> #include "login.h" int main(int argc, char *argv[]) { QApplication app(argc, argv); QLogin login; login.show(); return app.exec(); }
【分析】
1 改动后,省去了繁杂的调用步骤,只要采用
QLineEditWithIM *managerEdit; managerEdit = new QLineEditWithIM;
替代
QLineEdit *managerEdit; managerEdit = new QLineEdit;
在鼠标单击时,就可以弹出输入法了。
2 去掉qlineeditwithim.cpp中注释,即改为
#include "qlineeditwithim.h" QLineEditWithIM::QLineEditWithIM() { #ifdef Q_WS_QWS im = new InputMethod; installEventFilter(im); connect(im->keyboard,SIGNAL(setvalue(QString)),this,SLOT(setText(QString))); #endif }
在嵌入式版本中将弹出输入法,其他版本不会弹出输入法。
3 QLineEditWithIM重用了QLineEdit的方法,并增加了嵌入式输入法功能。而且没有增加任何调用开销。
【源码下载】
1 http://download.csdn.net/detail/tandesir/4378244
2 Qt设计模式1-8测试源码:http://download.csdn.net/detail/tandesir/4984275
声明:该源码仅供学习交流,勿用于商业目的。
转载请标明出处,仅供学习交流,勿用于商业目的
Copyright @ http://blog.csdn.net/tandesir