程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 設計模式(1)-模板模式(Template)

設計模式(1)-模板模式(Template)

編輯:C++入門知識

【描述】模板設計模式將常用的方法進行封裝,創建了一個實施一組方法和功能的抽象的對象。子類通常將這個對象作為模板用於設計。

【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
 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved