设计模式之外观模式

一、模式动机

  当需要简化并统一一个很大的接口或者一群复杂的接口时,使用外观模式。外观模式(Facade-Pattern),之所以这么称呼,是因为它将一个或数个类的复杂一切都隐藏在背后,只显露出一个干净美好的外观。

二、模式定义

  外观模式(Facade Pattern):提供了一个统一的接口,用来访问子系统中的一群接口。外观定义一个高层接口,让子系统更容易使用。

这里写图片描述

三、模式示例

  你组装了一套杀手级的家庭影院系统,内含DVD播放器、投影仪、自动屏幕、环绕立体声,甚至还有爆米花。如下图所示:

这里写图片描述

  但是观赏电影需要操作很多步,打开爆米花机,开始爆米花,将灯光调暗,放下屏幕,将投影机的输入切换到DVD…打开DVD播放器,开始播放DVD。现在用外观模式,一键搞定。

C++代码实现

#include <iostream>
#include <string>

using namespace std;

class TheaterLights
{
public:
    TheaterLights();
    ~TheaterLights();
    void on(){ cout << "Theater Lights On" << endl; }
    void off(){ cout << "Theater Lights Off" << endl; }
    void dim(int val){ cout << "Theater Lights Dim" << endl; }

private:

};

TheaterLights::TheaterLights()
{
}

TheaterLights::~TheaterLights()
{
}

class PopcomPopper
{
public:
    PopcomPopper();
    ~PopcomPopper();
    void on(){ cout << "PopcomPopper On" << endl; }
    void off(){ cout << "PopcomPopper Off" << endl; }
    void pop(){ cout << "PopcomPopper Pop" << endl; }

private:

};

PopcomPopper::PopcomPopper()
{
}

PopcomPopper::~PopcomPopper()
{
}

class Screen
{
public:
    Screen();
    ~Screen();
    void down(){ cout << "Screen Down" << endl; }
    void up(){ cout << "Screen Up" << endl; }

private:

};

Screen::Screen()
{
}

Screen::~Screen()
{
}

class Amplifier;

class Tuner
{
public:
    Tuner();
    ~Tuner();
    void on(){ cout << "Tuner On" << endl; }
    void off(){ cout << "Tuner Off" << endl; }
    void setAmplifier(Amplifier* am) { amplifier = am; }

private:
    Amplifier* amplifier;
};

Tuner::Tuner()
{
}

Tuner::~Tuner()
{
}

class CdPlayer
{
public:
    CdPlayer();
    ~CdPlayer();
    void on(){ cout << "CdPlayer On" << endl; }
    void off(){ cout << "CdPlayer Off" << endl; }
    void setAmplifier(Amplifier* am) { amplifier = am; }

private:
    Amplifier* amplifier;

};

CdPlayer::CdPlayer()
{
}

CdPlayer::~CdPlayer()
{
}

class DvdPlayer
{
public:
    DvdPlayer();
    ~DvdPlayer();
    void on(){ cout << "DvdPlayer On" << endl; }
    void off(){ cout << "DvdPlayer Off" << endl; }
    void setAmplifier(Amplifier* am) { amplifier = am; }

private:
    Amplifier* amplifier;

};

DvdPlayer::DvdPlayer()
{
}

DvdPlayer::~DvdPlayer()
{
}

class Projector
{
public:
    Projector();
    ~Projector();
    void on(){ cout << "DvdPlayer On" << endl; }
    void off(){ cout << "DvdPlayer Off" << endl; }
    void setDvdPlayer(DvdPlayer* player) { dvdPlayer = player; }

private:
    DvdPlayer* dvdPlayer;

};

Projector::Projector()
{
}

Projector::~Projector()
{
}

class Amplifier
{
public:
    Amplifier();
    ~Amplifier();
    void on(){ cout << "Amplifier On" << endl; }
    void off(){ cout << "Amplifier Off" << endl; }
    void setDvdPlayer(DvdPlayer* player) { dvdPlayer = player; }
    void setStereoSound(){ cout << "Amplifier Set StereoSound" << endl; }
    void setVolume(int volume){ cout << "Amplifier Set Volume" << endl; }

private:
    DvdPlayer* dvdPlayer;

};

Amplifier::Amplifier()
{
}

Amplifier::~Amplifier()
{
}


class HomeTheaterFacade
{
public:
    HomeTheaterFacade(Amplifier* amp, Tuner* tuner, DvdPlayer* dvd, CdPlayer* cd, Projector* projector, TheaterLights* lights, PopcomPopper* poper);
    ~HomeTheaterFacade();
    void watchMovie(string movie);

private:
    Amplifier* amp;
    Tuner* tuner;
    DvdPlayer* dvd;
    CdPlayer* cd;
    Projector* projector;
    TheaterLights* lights;
    Screen* screen;
    PopcomPopper* poper;
};

HomeTheaterFacade::HomeTheaterFacade(Amplifier* amp, Tuner* tuner, DvdPlayer* dvd, CdPlayer* cd, Projector* projector, TheaterLights* lights, PopcomPopper* poper)
    :amp(amp),
    tuner(tuner),
    dvd(dvd),
    cd(cd),
    projector(projector),
    lights(lights),
    poper(poper)
{
}

HomeTheaterFacade::~HomeTheaterFacade()
{
}

void HomeTheaterFacade::watchMovie(string movie) 
{ 
    cout << "Get ready to watch " + movie << endl; 
    poper->on();
    poper->pop();
    lights->dim(10);
    screen->down();
    projector->on();
    amp->on();
    amp->setStereoSound();
    amp->setVolume(5);
    dvd->on();
}



int _tmain(int argc, _TCHAR* argv[])
{
    TheaterLights* lights = new TheaterLights;
    PopcomPopper* poper = new PopcomPopper;
    Screen* screen = new Screen;
    Tuner* tuner = new Tuner;
    CdPlayer* cd = new CdPlayer;
    DvdPlayer* dvd = new DvdPlayer;
    Projector* projector = new Projector;
    Amplifier* amp = new Amplifier;
    projector->setDvdPlayer(dvd);
    dvd->setAmplifier(amp);
    cd->setAmplifier(amp);
    tuner->setAmplifier(amp);
    amp->setDvdPlayer(dvd);

    HomeTheaterFacade  homeTheater(amp, tuner, dvd, cd, projector, lights, poper);
    homeTheater.watchMovie("1942");

    system("pause");
    return 0;
}

运行结果:

这里写图片描述

四、分析总结

   外观模式将客户从一个复杂的子系统中解耦。实现一个外观,需要将子系统组合进外观中,然后将工作委托给子系统执行。

优点

  • 实现了子系统与客户之间的松耦合关系,这使得子系统的组件变化不会影响到调用它的客户类,只需要调整外观类即可
  • 只是提供了一个访问子系统的统一入口,并不影响用户直接使用子系统类

缺点

  • 在不引入抽象外观类的情况下,增加新的子系统可能需要修改外观类或客户端的源代码,违背了“开放-关闭原则”。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值