外观模式

模式定义

外观模式(Facade),为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。

模式动机

  • 当要为一个复杂子系统提供一个简单接口时可以使用外观模式。该接口可以满足大多数用户的需求,而且用户也可以越过外观类直接访问子系统。
  • 客户程序与多个子系统之间存在很大的依赖性。引入外观类将子系统与客户以及其他子系统解耦,可以提高子系统的独立性和可移植性。
  • 在层次化结构中,可以使用外观模式定义系统中每一层的入口,层与层之间不直接产生联系,而通过外观类建立联系,降低层之间的耦合度。

UML类图

外观模式

源码实现

  • hero.h
#ifndef HERO_H
#define HERO_H
#include <QDebug>

class Hero
{
public:
    Hero(QString name):m_Name(name){}
    ~Hero(){}

    inline void ZhongDan() { qDebug() << m_Name << " 中单";}
    inline void DaYe() { qDebug() << m_Name << " 打野";}
    inline void FuZhu() { qDebug() << m_Name << " 辅助";}
    inline void FaYu() { qDebug() << m_Name << " 发育";}
    inline void KangYa() { qDebug() << m_Name << " 抗压";}
protected:
    QString m_Name;
};

class ZhenJi : public Hero
{
public:
    ZhenJi():Hero("甄姬"){}
    ~ZhenJi(){}
};

class ZhaoYun : public Hero
{
public:
    ZhaoYun():Hero("赵云"){}
    ~ZhaoYun(){}
};

class XiangXiang : public Hero
{
public:
    XiangXiang():Hero("大小姐"){}
    ~XiangXiang(){}
};

class LianPo : public Hero
{
public:
    LianPo():Hero("廉颇"){}
    ~LianPo(){}
};

class LvBu : public Hero
{
public:
    LvBu():Hero("吕布"){}
    ~LvBu(){}
};

#endif // HERO_H

  • facade.h
#ifndef FACADE_H
#define FACADE_H
/************************************
    * @brief	: 用外观模式封装几个不同的子系统,
    * 子系统的操作统一放到外观模式的方法去
    * 峡谷系统安排:
    * 外观类:游戏不同的阵容组合
    * 英雄类:不同的英雄,可以打不同的位置
    * 外观类组合不同的英雄,得到一个胜率值
    * @author	:   wzx
    * @date	:   2020-04-17
    * @project	:  Facade
*************************************/
#include "hero.h"

class Facade
{
public:
    Facade();
    ~Facade();
    double LineUpA();
    double LineUpB();
    double LineUpC();

private:
    XiangXiang* m_XX;
    ZhaoYun*    m_ZY;
    LvBu*   m_LB;
    LianPo* m_LP;
    ZhenJi* m_ZJ;
};

#endif // FACADE_H

  • facade.cpp
#include "facade.h"
#define DELEOBJECT(x) if(x == nullptr) { delete x; x = nullptr;}
Facade::Facade()
{
    m_XX = new XiangXiang();
    m_ZY = new ZhaoYun();
    m_LB = new LvBu();
    m_LP = new LianPo();
    m_ZJ = new ZhenJi();
}

Facade::~Facade()
{
    DELEOBJECT(m_XX);
    DELEOBJECT(m_ZY);
    DELEOBJECT(m_LB);
    DELEOBJECT(m_LP);
    DELEOBJECT(m_ZJ);
}

double Facade::LineUpA()
{
    m_XX->FaYu();
    m_ZY->DaYe();
    m_LB->KangYa();
    m_LP->FuZhu();
    m_ZJ->ZhongDan();
    return 0.88;
}

double Facade::LineUpB()
{
    m_XX->FaYu();
    m_ZY->KangYa();
    m_LB->DaYe();
    m_LP->FuZhu();
    m_ZJ->ZhongDan();
    return 0.40;
}

double Facade::LineUpC()
{
    m_XX->FaYu();
    m_ZY->DaYe();
    m_LB->ZhongDan();
    m_LP->KangYa();
    m_ZJ->FuZhu();
    return 0.60;
}

  • main.cpp
#include <QCoreApplication>
#include "facade.h"

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    Facade facade;
    qDebug() << "胜率" << facade.LineUpA()*100 << "%" << endl;
    qDebug() << "胜率" << facade.LineUpB()*100 << "%" << endl;
    qDebug() << "胜率" << facade.LineUpB()*100 << "%" << endl;
    return a.exec();
}

  • 运行结果

“大小姐” 发育

“赵云” 打野

“吕布” 抗压

“廉颇” 辅助

“甄姬” 中单

胜率 88 %

“大小姐” 发育

“赵云” 抗压

“吕布” 打野

“廉颇” 辅助

“甄姬” 中单

胜率 40 %

“大小姐” 发育

“赵云” 抗压

“吕布” 打野

“廉颇” 辅助

“甄姬” 中单

胜率 40 %

优点

外观模式的优点

  • 对客户屏蔽子系统组件,减少了客户处理的对象数目并使得子系统使用起来更加容易。通过引入外观模式,客户代码将变得很简单,与之关联的对象也很少。
  • 实现了子系统与客户之间的松耦合关系,这使得子系统的组件变化不会影响到调用它的客户类,只需要调整外观类即可。
  • 降低了大型软件系统中的编译依赖性,并简化了系统在不同平台之间的移植过程,因为编译一个子系统一般不需要编译所有其他的子系统。一个子系统的修改对其他子系统没有任何影响,而且子系统内部变化也不会影响到外观对象。
  • 只是提供了一个访问子系统的统一入口,并不影响用户直接使用子系统类。
  • 完美的体现了依赖倒转原则和迪米特法则

缺点

外观模式的缺点

  • 不能很好地限制客户使用子系统类,如果对客户访问子系统类做太多的限制则减少了可变性和灵活性。
  • 在不引入抽象外观类的情况下,增加新的子系统可能需要修改外观类或客户端的源代码,违背了“开闭原则”。

版权声明:本文为wzxNote原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/wzxNote/p/12718427.html