设计模式(5)-装饰模式(Decorator)

【描述】不修改原代码的结构,通过装饰器给代码增加新功能。

【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输入法设计(嵌入式)

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

 

【源码下载】

1 http://download.csdn.net/detail/tandesir/4418929

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

 

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

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

 

 

 

 

 




 

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值