设计模式(1)-模板模式(Template)

【更新】

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

[html]  view plain copy
  1. #ifndef DRAWTEMPLATE_H  
  2. #define DRAWTEMPLATE_H  
  3.   
  4. #include <QString>  
  5. class DrawTemplate  
  6. {  
  7. public:  
  8.     DrawTemplate();  
  9.   
  10. protected:  
  11.     virtual void draw();  
  12.     virtual void setMethod(QString method) const = 0;  
  13.       
  14. public:  
  15.     virtual QString getMethod();  
  16. };  
  17.   
  18. #endif // DRAWTEMPLATE_H  


drawtemplate.cpp

[html]  view plain copy
  1. #include <QDebug>  
  2. #include "drawtemplate.h"  
  3.   
  4. DrawTemplate::DrawTemplate()  
  5. {  
  6.     qDebug()<<"construct DrawTemplate";  
  7. }  
  8.   
  9. void DrawTemplate::draw()  
  10. {  
  11.     qDebug()<<"DrawTemplate::draw()";  
  12.     setMethod(getMethod());  
  13. }  
  14.   
  15. QString DrawTemplate::getMethod()  
  16. {  
  17.     QString test = "Method::DrawTemplate";  
  18.     qDebug()<<"DrawTemplate::getMethod()";  
  19.     return test;  
  20. }  


draw1.h

[html]  view plain copy
  1. #ifndef DRAW1_H  
  2. #define DRAW1_H  
  3.   
  4. #include "drawtemplate.h"  
  5.   
  6. class Draw1 : public DrawTemplate  
  7. {  
  8. public:  
  9.     Draw1();  
  10.   
  11. public:  
  12.     void draw();  
  13.   
  14.     void setMethod(QString) const;  
  15. };  
  16.   
  17. #endif // DRAW1_H  


draw1.cpp

[html]  view plain copy
  1. #include <QDebug>  
  2. #include "draw1.h"  
  3.   
  4. Draw1::Draw1()  
  5. {  
  6.     qDebug()<<"construct Draw1";  
  7. }  
  8.   
  9. void Draw1::draw()  
  10. {  
  11.     qDebug()<<"Draw1::draw()";  
  12.     setMethod(getMethod());  
  13. }  
  14.   
  15. void Draw1::setMethod(QString method) const  
  16. {  
  17.     qDebug()<<QString("Draw1::setMethod(%1)").arg(method);  
  18. }  


draw2.h

[html]  view plain copy
  1. #ifndef DRAW2_H  
  2. #define DRAW2_H  
  3.   
  4. #include "drawtemplate.h"  
  5.   
  6. class Draw2 : public DrawTemplate  
  7. {  
  8. public:  
  9.     Draw2();  
  10.   
  11. public:  
  12.     void draw();  
  13.   
  14.     QString getMethod();  
  15.     void setMethod(QString method) const;  
  16. };  
  17.   
  18. #endif // DRAW2_H  


draw2.cpp

[html]  view plain copy
  1. #include <QDebug>  
  2. #include "draw2.h"  
  3.   
  4. Draw2::Draw2()  
  5. {  
  6.     qDebug()<<"construct Draw2";  
  7. }  
  8.   
  9. void Draw2::draw()  
  10. {  
  11.     qDebug()<<"Draw2::draw()";  
  12.     setMethod(getMethod());  
  13. }  
  14.   
  15. QString Draw2::getMethod()  
  16. {  
  17.     QString test = "Method::Draw2";  
  18.     qDebug()<<"Draw2::getMethod()";  
  19.     return test;  
  20. }  
  21.   
  22. void Draw2::setMethod(QString method) const  
  23. {  
  24.     qDebug()<<QString("Draw2::setMethod(%1)").arg(method);  
  25. }  

 

main.cpp

[html]  view plain copy
  1. #include "drawtemplate.h"  
  2. #include "draw1.h"  
  3. #include "draw2.h"  
  4.   
  5. int main(void)  
  6. {  
  7.     Draw1 draw1;  
  8.     draw1.draw();  
  9.   
  10.     Draw2 draw2;  
  11.     draw2.draw();  
  12. }  

 

【运行结果】

[html]  view plain copy
  1. construct DrawTemplate   
  2. construct Draw1   
  3. Draw1::draw()   
  4. DrawTemplate::getMethod()   
  5. "Draw1::setMethod(Method::DrawTemplate)"   
  6. construct DrawTemplate   
  7. construct Draw2   
  8. Draw2::draw()   
  9. Draw2::getMethod()   
  10. "Draw2::setMethod(Method::Draw2)"  


【实例剖析】

*该实例不是严格的模板模式,因为并没有覆盖模板中的方法。有好的见解,欢迎留言!(2012-09-06)

Qt输入法设计(嵌入式)一文中介绍了一种输入法的设计,在使用时,需要对控件对象的名称进行指定,并对每个QLineEdit对象绑定输入法对象。能否有一种方法,使得编辑框自带输入法对象?

下面利用模板模式,将QLineEdit作为模板,派生一个QLineEditWithIM,使得QLineEditWithIM自带输入法,使用就像QLineEdit一样简单。UML图如图2所示:

图2

【代码清单】

仅贴出改动的部分,省略了keyboard.h、keyboard.cpp代码。详请参考Qt输入法设计(嵌入式)

inputmethod.h

[html]  view plain copy
  1. #ifndef INPUTMETHOD_H  
  2. #define INPUTMETHOD_H  
  3.   
  4. #include "keyboard.h"  
  5.   
  6. class InputMethod : public KeyBoard  
  7. {  
  8.     Q_OBJECT  
  9. public:  
  10.     InputMethod();  
  11.     ~InputMethod();  
  12.   
  13.     bool eventFilter(QObject *obj, QEvent *event);  
  14.   
  15. public:  
  16.     KeyBoard *keyboard;  
  17.   
  18. public:  
  19.     void showKeyBoard();  
  20. };  
  21.   
  22. #endif // INPUTMETHOD_H  


inputmethod.cpp

[html]  view plain copy
  1. #include <QDebug>  
  2. #include "inputmethod.h"  
  3.   
  4. InputMethod::InputMethod()  
  5. {  
  6.     keyboard = new KeyBoard;  
  7.     setWindowFlags(Qt::Tool|Qt::WindowStaysOnTopHint|Qt::FramelessWindowHint);  
  8. }  
  9.   
  10. InputMethod::~InputMethod()  
  11. {  
  12.     delete keyboard;  
  13. }  
  14.   
  15. /*  
  16. * Name : void eventFilter(QObject *obj, QEvent *event);  
  17. * Type : QEvent  
  18. * Func : judge input method event  
  19. * In   : QObject,QEvent  
  20. * Out  : bool  
  21. */  
  22. bool InputMethod::eventFilter(QObject *obj, QEvent *event)  
  23. {  
  24.     if(event->type()==QEvent::MouseButtonPress)  
  25.     {  
  26.         showKeyBoard();  
  27.         return true;  
  28.     }  
  29.   
  30.     return QObject::eventFilter(obj,event);  
  31. }  
  32.   
  33.   
  34. /*  
  35. * Name : void showKeyBoard();  
  36. * Type : function  
  37. * Func : show keyBoard  
  38. * In   : Null  
  39. * Out  : Null  
  40. */  
  41. void InputMethod::showKeyBoard()  
  42. {  
  43.     keyboard->setWindowFlags(Qt::Tool|Qt::WindowStaysOnTopHint|Qt::FramelessWindowHint);  
  44.     keyboard->move(50,120);  
  45.     keyboard->exec();  
  46. }  


qlineeditwithim.h

[html]  view plain copy
  1. #ifndef QLINEEDITWITHIM_H  
  2. #define QLINEEDITWITHIM_H  
  3.   
  4. #include <QLineEdit>  
  5. #include "inputmethod.h"  
  6.   
  7. class QLineEditWithIM : public QLineEdit  
  8. {  
  9. public:  
  10.     QLineEditWithIM();  
  11.   
  12. private:  
  13.     InputMethod *im;  
  14. };  
  15.   
  16. #endif // QLINEEDITWITHIM_H  


qlineeditwithim.cpp

[html]  view plain copy
  1. #include "qlineeditwithim.h"  
  2.   
  3. QLineEditWithIM::QLineEditWithIM()  
  4. {  
  5. //#ifdef Q_WS_QWS  
  6.     im = new InputMethod;  
  7.     installEventFilter(im);  
  8.     connect(im->keyboard,SIGNAL(setvalue(QString)),this,SLOT(setText(QString)));  
  9. //#endif  
  10. }  


login.h

[html]  view plain copy
  1. #ifndef LOGIN_H  
  2. #define LOGIN_H  
  3.   
  4. #include <QDialog>  
  5. #include "qlineeditwithim.h"  
  6.   
  7. class QLabel;  
  8. class QLineEdit;  
  9. class QDialogButtonBox;  
  10.   
  11. class QLogin : public QDialog  
  12. {  
  13.     Q_OBJECT  
  14.   
  15. public:  
  16.     QLogin();  
  17.     ~QLogin();  
  18.   
  19. public:  
  20.   
  21.     QLabel *managerLabel;  
  22.     QLabel *passwdLabel;  
  23.   
  24.     QLineEditWithIM *managerEdit;  
  25.     QLineEditWithIM *passwdEdit;  
  26.   
  27.     QPushButton *okButton;  
  28.     QPushButton *cancelButton;  
  29.     QDialogButtonBox *buttonBox;  
  30.   
  31. signals:  
  32.     void Authorize();  
  33.   
  34. private slots:  
  35.     void login();  
  36.     void cancel();  
  37.   
  38. };  
  39.   
  40. #endif // LOGIN_H  


login.cpp

[html]  view plain copy
  1. #include <QtGui>  
  2. #include "login.h"  
  3.   
  4. QLogin::QLogin()  
  5. {  
  6.     managerLabel = new QLabel(tr("&Manager:"));  
  7.     managerEdit = new QLineEditWithIM();  
  8.     managerLabel->setBuddy(managerEdit);  
  9.   
  10.     passwdLabel = new QLabel(tr("&Passwd:"));  
  11.     passwdEdit = new QLineEditWithIM;  
  12.     passwdEdit->setEchoMode(QLineEdit::Password);  
  13.     passwdLabel->setBuddy(passwdEdit);  
  14.   
  15.     okButton = new QPushButton(tr("&Login"));  
  16.     cancelButton = new QPushButton("&Cancel");  
  17.   
  18.     okButton->setDefault(true);  
  19.   
  20.     buttonBox = new QDialogButtonBox;  
  21.     buttonBox->addButton(okButton, QDialogButtonBox::ActionRole);  
  22.     buttonBox->addButton(cancelButton, QDialogButtonBox::AcceptRole);  
  23.   
  24.     connect(okButton, SIGNAL(clicked()), this, SLOT(login()));  
  25.     connect(cancelButton, SIGNAL(clicked()), this, SLOT(cancel()));  
  26.   
  27.     QHBoxLayout *topLayout = new QHBoxLayout;  
  28.     topLayout->addWidget(managerLabel);  
  29.     topLayout->addWidget(managerEdit);  
  30.   
  31.     QHBoxLayout *midLayout = new QHBoxLayout;  
  32.     midLayout->addWidget(passwdLabel);  
  33.     midLayout->addWidget(passwdEdit);  
  34.   
  35.     QVBoxLayout *mainLayout = new QVBoxLayout;  
  36.     mainLayout->addLayout(topLayout);  
  37.     mainLayout->addLayout(midLayout);  
  38.     mainLayout->addWidget(buttonBox);  
  39.     mainLayout->setMargin(20);  
  40.     setLayout(mainLayout);  
  41.     managerEdit->setFocus();    
  42.   
  43.     QIcon icon;  
  44.     icon.addFile(QString::fromUtf8(":/new/main/picture/logo.png"), QSize(), QIcon::Normal, QIcon::Off);  
  45.     setWindowIcon(icon);  
  46.     setWindowTitle("Login");  
  47. }  
  48.   
  49. QLogin::~QLogin()  
  50. {  
  51.     //qDebug()<<"login close";  
  52.     delete managerLabel;  
  53.     delete managerEdit;  
  54.     delete passwdLabel;  
  55.     delete passwdEdit;  
  56.     delete okButton;  
  57.     delete cancelButton;  
  58. }  
  59.   
  60. /*  
  61. * Name : void login()  
  62. * Type : slot  
  63. * Func : login when authorize  
  64. * In   : Null  
  65. * Out  : Null  
  66. */  
  67. void QLogin::login()  
  68. {  
  69.     qDebug()<<managerEdit->text();  
  70.     qDebug()<<passwdEdit->text();  
  71. }  
  72.   
  73.   
  74. /*  
  75. * Name : void cancel()  
  76. * Type : slot  
  77. * Func : cancel login  
  78. * In   : Null  
  79. * Out  : Null  
  80. */  
  81. void QLogin::cancel()  
  82. {  
  83.     managerEdit->clear();  
  84.     passwdEdit->clear();  
  85.     close();  
  86. }  


main.cpp

[html]  view plain copy
  1. #include <QtGui/QApplication>  
  2. #include "login.h"  
  3.   
  4. int main(int argc, char *argv[])  
  5. {  
  6.     QApplication app(argc, argv);  
  7.   
  8.     QLogin login;  
  9.     login.show();  
  10.     return app.exec();  
  11. }  


 

【分析】

1 改动后,省去了繁杂的调用步骤,只要采用

[html]  view plain copy
  1. QLineEditWithIM *managerEdit;  
  2. managerEdit = new QLineEditWithIM;  

替代

[html]  view plain copy
  1. QLineEdit *managerEdit;  
  2. managerEdit = new QLineEdit;  

在鼠标单击时,就可以弹出输入法了。

2 去掉qlineeditwithim.cpp中注释,即改为

[html]  view plain copy
  1. #include "qlineeditwithim.h"  
  2.   
  3. QLineEditWithIM::QLineEditWithIM()  
  4. {  
  5. #ifdef Q_WS_QWS  
  6.     im = new InputMethod;  
  7.     installEventFilter(im);  
  8.     connect(im->keyboard,SIGNAL(setvalue(QString)),this,SLOT(setText(QString)));  
  9. #endif  
  10. }  

在嵌入式版本中将弹出输入法,其他版本不会弹出输入法。

 

3 QLineEditWithIM重用了QLineEdit的方法,并增加了嵌入式输入法功能。而且没有增加任何调用开销。

 

【源码下载】

http://download.csdn.net/detail/tandesir/4378244

2 Qt设计模式1-8测试源码:http://download.csdn.net/detail/tandesir/4984275
 声明:该源码仅供学习交流,勿用于商业目的。

 

 

 

转载请标明出处,仅供学习交流,勿用于商业目的

Copyright @ http://blog.csdn.net/tandesir

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值