【描述】不修改原代码的结构,通过装饰器给代码增加新功能。
【UML图】
图1 UML图
(1) 原始代码为Component类,提供了operation操作;
(2) 装饰器为Decorator类,提供了扩展的operation功能;
(3) 注意与模板模式(设计模式(1)-模板模式(Template))的区别。
【示例代码】
component.h
#ifndef COMPONENT_H
#define COMPONENT_H
class Component
{
public:
Component();
public:
virtual void operation();
};
#endif // COMPONENT_H
component.cpp
#include <QDebug>
#include "component.h"
Component::Component()
{
qDebug()<<"construct Component";
}
void Component::operation()
{
qDebug()<<"Base Function";
}
decorator.h
#ifndef DECORATOR_H
#define DECORATOR_H
#include "component.h"
class Decorator : public Component
{
public:
Decorator(Component component);
private:
Component component;
public:
void operation();
};
#endif // DECORATOR_H
decorator.cpp
#include <QDebug>
#include "decorator.h"
Decorator::Decorator(Component component)
{
qDebug()<<"construct Decorator";
this->component = component;
}
void Decorator::operation()
{
component.operation();
qDebug()<<"Extend Function";
}
main.cpp
#include "component.h"
#include "decorator.h"
int main(void)
{
Component component;
component.operation();
Decorator decorator(component);
decorator.operation();
return 0;
}
【运行结果】
construct Component
Base Function
construct Component
construct Component
construct Decorator
Base Function
Extend Function
【结果分析】
借助装饰器,在没有改变原始代码的前提下,给代码增加了新功能。
【实例剖析】
设计模式(1)-模板模式(Template)一文介绍了一种改进的Qt嵌入式输入法,下面利用装饰模式对代码进行改写。先看UML图:
图2
(1) 原始代码为QLineEdit类;
(2) 装饰器为QLineEditWithIM类,提供了installIM()方法。
【代码清单】
下面仅贴出修改的部分,详细代码请参考Qt输入法设计(嵌入式)以及设计模式(1)-模板模式(Template)一文。
qlineeditwithim.h
#ifndef QLINEEDITWITHIM_H
#define QLINEEDITWITHIM_H
#include <QLineEdit>
#include "inputmethod.h"
class QLineEditWithIM : public QLineEdit
{
public:
QLineEditWithIM(QLineEdit *lineEdit);
~QLineEditWithIM();
private:
QLineEdit *lineEdit;
InputMethod *im;
public:
void installIM();
};
#endif // QLINEEDITWITHIM_H
qlineeditwithim.cpp
#include "qlineeditwithim.h"
QLineEditWithIM::QLineEditWithIM(QLineEdit *lineEdit)
{
//#ifdef Q_WS_QWS
im = new InputMethod;
this->lineEdit = lineEdit;
//#endif
}
QLineEditWithIM::~QLineEditWithIM()
{
delete im;
}
void QLineEditWithIM::installIM()
{
//#ifdef Q_WS_QWS
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_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
#include <QtGui>
#include "login.h"
QLogin::QLogin()
{
managerLabel = new QLabel(tr("&Manager:"));
QLineEdit *_managerEdit = new QLineEdit;
managerEdit = new QLineEditWithIM(_managerEdit);
managerEdit->installIM();
managerLabel->setBuddy(managerEdit);
passwdLabel = new QLabel(tr("&Passwd:"));
QLineEdit *_passwdEdit = new QLineEdit;
passwdEdit = new QLineEditWithIM(_passwdEdit);
passwdEdit->installIM();
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()<<"destruct login";
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();
}
【分析】
(1) 与模板模式的关键区别在于,QLineEditWithIM引用了QLineEdit对象;
(2) 模板模式调用的代码为
QLineEditWithIM *managerEdit;
managerEdit = new QLineEditWithIM;
装饰模式调用的代码为
QLineEdit *_managerEdit = new QLineEdit;
managerEdit = new QLineEditWithIM(_managerEdit);
managerEdit->installIM();
实质上,在模板模式中,我们并没有使用QLineEditWithIM提供的引用对象lineEdit。而运用模板模式调用也比较简单。可见,此处将QLineEdit想象为一个模板,运用模板模式更为合适。
【学习参考】
(1) Qt输入法设计(嵌入式)
【源码下载】
1 http://download.youkuaiyun.com/detail/tandesir/4418929
2 Qt设计模式1-8测试源码:http://download.youkuaiyun.com/detail/tandesir/4984275
声明:该源码仅供学习交流,勿用于商业目的。
转载请标明出处,仅供学习交流,勿用于商业目的
Copyright @ http://blog.youkuaiyun.com/tandesir