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