设计模式(1)-模板模式(Template)
来源:互联网 发布:淘宝宝贝突然搜索不到 编辑:程序博客网 时间:2024/04/30 07:08
【更新】
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_OBJECTpublic: 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_OBJECTpublic: 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
- 设计模式(1)-模板模式(Template)
- 设计模式(1)-模板模式(Template)
- Template(模板)设计模式
- 设计模式之模板模式:Template模式
- 设计模式之模板模式:Template模式
- 模板方法(Template)设计模式
- 设计模式之(十二)模板模式Template
- 设计模式之模板方法模式Template
- java设计模式--模板(Template)模式--03
- 设计模式----模板方法模式(Template Method)
- [设计模式]模板方法模式(Template Method)
- 设计模式之模板模式(Template Model)
- 设计模式(12) - Template模板方法模式
- C++设计模式实现--模板(Template)模式
- 设计模式--模板方法模式Template
- 【设计模式】-模板方法模式(Template)
- [C++设计模式]template 模板方法模式
- 设计模式—模板模式(Template Pattern)
- iPhone上实现流媒体播放器
- 九度1018
- VC++学习笔记(六)
- OPENCV haarcascade文件解析
- F1论坛快速回复工具...
- 设计模式(1)-模板模式(Template)
- php5中调用webservice
- matlab 连接 mysql 数据库
- 尚观-嵌入式学习最佳入门课程
- 【转】c/c++资源(源码、开发工具、开发库)
- JNI多线程
- Android"重力加速度传感器"从驱动到应用层全程分析
- 使li横排显示并且ul位于div的中间位置
- C++程序设计报告(16-1)