设计模式(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

 

 

 

 


 

 

 

 

原创粉丝点击