【更新】
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