您的位置:首页 > 其它

设计模式(4)-外观模式(Facade)

2012-07-05 16:09 239 查看
【描述】外观模式通过在对必需的逻辑和方法的集合前创建简单的外观接口,隐藏来自调用的复杂性。

【UML图】



图1 外观模式UML图
(1) AirCondition、Fan、Light电器类定义了一个on和off的方法;
(2) Facade类定义了on和off的方法,并调用了AirCondition、Fan、Light类的on和off方法,隐藏调用的复杂性;
(3) 与组合模式的不同在于Facade和AirCondition、Fan、Light电器类是关联的关系,而不是组合的关系。

【示例代码】
aircondition.h
#ifndef AIRCONDITION_H
#define AIRCONDITION_H

class AirCondition
{
public:
    AirCondition();
    ~AirCondition();

public:
    void on();
    void off();
};

#endif // AIRCONDITION_H


aircondition.cpp
#include <QDebug>
#include "aircondition.h"

AirCondition::AirCondition()
{
    qDebug()<<"construct AirCondition";
}

AirCondition::~AirCondition()
{
    qDebug()<<"destruct AirCondition";
}

void AirCondition::on()
{
    qDebug()<<"AirCondition on";
}

void AirCondition::off()
{
    qDebug()<<"AirCondition off";
}


fan.h
#ifndef FAN_H
#define FAN_H

class Fan
{
public:
    Fan();
    ~Fan();

public:
    void on();
    void off();
};

#endif // FAN_H


fan.cpp
#include <QDebug>
#include "fan.h"

Fan::Fan()
{
    qDebug()<<"construct Fan";
}

Fan::~Fan()
{
    qDebug()<<"destruct Fan";
}

void Fan::on()
{
    qDebug()<<"Fan on";
}

void Fan::off()
{
    qDebug()<<"Fan off";
}


light.h
#ifndef LIGHT_H
#define LIGHT_H

class Light
{
public:
    Light();
    ~Light();

public:
    void on();
    void off();
};

#endif // LIGHT_H


light.cpp
#include <QDebug>
#include "light.h"

Light::Light()
{
    qDebug()<<"construct Light";
}

Light::~Light()
{
    qDebug()<<"destruct Light";
}

void Light::on()
{
    qDebug()<<"Light on";
}

void Light::off()
{
    qDebug()<<"Light off";
}


facade.h
#ifndef FACADE_H
#define FACADE_H

#include "aircondition.h"
#include "fan.h"
#include "light.h"

class Facade
{
public:
    Facade();
    ~Facade();

private:
    AirCondition *_airCondition;
    Fan *_fan;
    Light *_light;

public:
    void on();
    void off();
};

#endif // FACADE_H


facade.cpp
#include <QDebug>
#include "facade.h"

Facade::Facade()
{
    qDebug()<<"construct Facade";

    _airCondition = new AirCondition;
    _fan = new Fan;
    _light = new Light;
}

Facade::~Facade()
{
    qDebug()<<"destruct Facade";

    delete _airCondition;
    delete _fan;
    delete _light;
}

void Facade::on()
{
    qDebug()<<"Facade::on";

    _airCondition->on();
    _fan->on();
    _light->on();
}

void Facade::off()
{
    qDebug()<<"Facade::off";

    _airCondition->off();
    _fan->off();
    _light->off();
}


main.cpp
#include "facade.h"

int main(void)
{
    Facade *facade = new Facade;
    facade->on();
    facade->off();

    return 0;
}


【运行结果】
construct Facade 
construct AirCondition 
construct Fan 
construct Light 
Facade::on 
AirCondition on 
Fan on 
Light on 
Facade::off 
AirCondition off 
Fan off 
Light off


【结果分析】

Facade的on方法为电器类on方法的集合提供了接口,可以根据需要定义不同的on方法。

【实例剖析】
外观模式是我们常用的设计模式,有时候不知不觉就用到了。看下面一个登陆界面的设计实例。
先看UML图,



图2
(1) LoginDlg继承了QDialog类,实现用户登录鉴权;
(2) LoginDlg调用了QLabel、QLineEdit进行界面设计,界面设计的代码单独分离,构建了外观方法,提供给构造函数调用;
(3) 提供了cancel方法,cancel调用了QLineEdit相关对象的clear方法,实质上是一个外观打包。

【代码清单】
LoginDlg::LoginDlg()
{
    //qDebug()<<"construct_login";
    initDlg();
    initConnect();
}

LoginDlg::~LoginDlg()
{
    delete label_username;
    delete label_passwd;
    delete lineEdit_username;
    delete lineEdit_passwd;
    delete pushButton_ok;
    delete pushButton_cancel;

    //qDebug()<<"desstruct_login";
}

void LoginDlg::initDlg()
{
    setWindowFlags(Qt::FramelessWindowHint);
    label_username = new QLabel;
    label_username->setText(tr("用 户 名:"));
    label_passwd = new QLabel;
    label_passwd->setText(tr("用户密码:"));
    lineEdit_username = new QLineEdit;
    lineEdit_username->setFocus();
    lineEdit_passwd = new QLineEdit;
    lineEdit_passwd->setEchoMode(QLineEdit::Password);

    pushButton_ok = new QPushButton;
    pushButton_ok->setText(tr("确定"));
    pushButton_ok->setIcon(style()->standardIcon(QStyle::SP_DialogOkButton));
    pushButton_cancel = new QPushButton;
    pushButton_cancel->setText(tr("取消"));
    pushButton_cancel->setIcon(style()->standardIcon(QStyle::SP_DialogCancelButton));

    QGridLayout *gridLayout = new QGridLayout;
    gridLayout->addWidget(label_username,0,0);
    gridLayout->addWidget(lineEdit_username,0,1);
    gridLayout->addWidget(label_passwd,1,0);
    gridLayout->addWidget(lineEdit_passwd,1,1);

    QHBoxLayout *buttonLayout = new QHBoxLayout;
    buttonLayout->addStretch();
    buttonLayout->addWidget(pushButton_ok);
    buttonLayout->addStretch();
    buttonLayout->addWidget(pushButton_cancel);
    buttonLayout->addStretch();

    QVBoxLayout *mainLayout = new QVBoxLayout;
    mainLayout->addLayout(gridLayout);
    mainLayout->addLayout(buttonLayout);
    mainLayout->addStretch();

    setLayout(mainLayout);
}

void LoginDlg::initConnect()
{
    connect(pushButton_cancel,SIGNAL(clicked()),this,SLOT(cancel()));
    connect(pushButton_ok,SIGNAL(clicked()),this,SLOT(Login()));
}

void LoginDlg::cancel()
{
    lineEdit_username->clear();
    lineEdit_passwd->clear();

    close();
}


LoginDlg类中initDlg、cancel方法,应用了外观模式。cancel方法运用了多态特性,覆盖了LoginDlg的父类QDialog的cancel方法,是LoginDlg类的一个私有槽函数。外观模式的应用使得构造函数更为清晰,initConnect方法更为简单。这时可以利用:
connect(pushButton_cancel,SIGNAL(clicked()),this,SLOT(cancel()));

来取代
connect(pushButton_cancel,SIGNAL(clicked()),lineEdit_username,SLOT(clear()));
connect(pushButton_cancel,SIGNAL(clicked()),lineEdit_passwd,SLOT(clear()));
connect(pushButton_cancel,SIGNAL(clicked()),this,SLOT(close()));


将界面设计的代码从构造函数中,单独分离,也是一种好的设计方式。

*对外观模式有更好的见解,欢迎留言,交流学习。

【源码下载】
Qt设计模式1-8测试源码:http://download.csdn.net/detail/tandesir/4984275

声明:该源码仅供学习交流,勿用于商业目的。

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

Copyright @ http://blog.csdn.net/tandesir
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: