【描述】模板設計模式將常用的方法進行封裝,創建了一個實施一組方法和功能的抽象的對象。子類通常將這個對象作為模板用於設計。
【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
[html] view plaincopyprint?#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
#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
[html] view plaincopyprint?#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;
}
#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
[html] view plaincopyprint?#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
#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
[html] view plaincopyprint?#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);
}
#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
[html] view plaincopyprint?#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
#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
[html] view plaincopyprint?#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);
}
#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
[html] view plaincopyprint?#include "drawtemplate.h"
#include "draw1.h"
#include "draw2.h"
int main(void)
{
Draw1 draw1;
draw1.draw();
Draw2 draw2;
draw2.draw();
}
#include "drawtemplate.h"
#include "draw1.h"
#include "draw2.h"
int main(void)
{
Draw1 draw1;
draw1.draw();
Draw2 draw2;
draw2.draw();
}
【運行結果】
[html] view plaincopyprint?construct DrawTemplate
construct Draw1
Draw1::draw()
DrawTemplate::getMethod()
"Draw1::setMethod(Method::DrawTemplate)"
construct DrawTemplate
construct Draw2
Draw2::draw()
Draw2::getMethod()
"Draw2::setMethod(Method::Draw2)"
construct DrawTemplate
construct Draw1
Draw1::draw()
DrawTemplate::getMethod()
"Draw1::setMethod(Method::DrawTemplate)"
construct DrawTemplate
construct Draw2
Draw2::draw()
Draw2::getMethod()
"Draw2::setMethod(Method::Draw2)"
【實例剖析】
Qt輸入法設計(嵌入式)一文中介紹了一種輸入法的設計,在使用時,需要對控件對象的名稱進行指定,並對每個QLineEdit對象綁定輸入法對象。能否有一種方法,使得編輯框自帶輸入法對象?
下面利用模板模式,將QLineEdit作為模板,派生一個QLineEditWithIM,使得QLineEditWithIM自帶輸入法,使用就像QLineEdit一樣簡單。UML圖如圖2所示:
圖2
【代碼清單】
僅貼出改動的部分,省略了keyboard.h、keyboard.cpp代碼。詳請參考Qt輸入法設計(嵌入式)
inputmethod.h
[html] view plaincopyprint?#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
#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
[html] view plaincopyprint?#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();
}
#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
[html] view plaincopyprint?#ifndef QLINEEDITWITHIM_H
#define QLINEEDITWITHIM_H
#include <QLineEdit>
#include "inputmethod.h"
class QLineEditWithIM : public QLineEdit
{
public:
QLineEditWithIM();
private:
InputMethod *im;
};
#endif // 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
[html] view plaincopyprint?#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
}
#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
[html] view plaincopyprint?#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
#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
[html] view plaincopyprint?#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();
}
#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
[html] view plaincopyprint?#include <QtGui/QApplication>
#include "login.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QLogin login;
login.show();
return app.exec();
}
#include <QtGui/QApplication>
#include "login.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QLogin login;
login.show();
return app.exec();
}
【分析】
1 改動後,省去了繁雜的調用步驟,只要采用
[html] view plaincopyprint?QLineEditWithIM *managerEdit;
managerEdit = new QLineEditWithIM;
QLineEditWithIM *managerEdit;
managerEdit = new QLineEditWithIM;
替代
[html] view plaincopyprint?QLineEdit *managerEdit;
managerEdit = new QLineEdit;
QLineEdit *managerEdit;
managerEdit = new QLineEdit;
在鼠標單擊時,就可以彈出輸入法了。
2 去掉qlineeditwithim.cpp中注釋,即改為
[html] view plaincopyprint?#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
} www.2cto.com
#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的方法,並增加了嵌入式輸入法功能。而且沒有增加任何調用開銷。
轉載請標明出處,僅供學習交流,勿用於商業目的
Copyright @ http://blog.csdn.net/tandesir
作者:tandesir