经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » Java相关 » 设计模式 » 查看文章
深入浅出《设计模式》之外观模式(C++)
来源:cnblogs  作者:尔广强  时间:2019/7/19 10:18:25  对本文有异议

前言

模式介绍

外观模式相比较之下比较简单,模式设计中定义是为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口是的这一子系统更加容易使用。

如果不理解呢,简单些说就是外观模式提供了为内部提供了同意的接口层,解耦了子系统和客户端,这样客户端只需要知道外观类存在即可,不需要知道具体子系统是如何实现的。举一个简单的例子,海参面馆中两个主打面食是:

  • 海参炒面

  • 辣根汤面

两个主打面食都由一个师傅来做,这个师傅会这两种面食的做法。具体的做法呢如下:
- 海参炒面
1. 剥蒜
2. 拉面
3. 做汤底
- 辣根汤面
1. 制作辣根
这两种面食都有复杂的做法,调用者如果直接调用这种步骤,会让调用者与师傅的耦合性很高,如果有一天制作步骤改了,辣根汤面要剥蒜,那就需要修改调用者接口,这样是不可以的。
所以这时候师傅就是一个外观类,调用者只需要和他说,我需要一份海参炒面或者辣根汤面即可,具体如何做,就是师傅的事情了。外部不需要管。UML类图如下:

UML类图

外观模式UML

代码实例

下面是剥蒜类实现,非常简单,只完成剥蒜动作即可。

  1. #ifndef GRALIC_H
  2. #define GRALIC_H
  3. class gralic
  4. {
  5. public:
  6. gralic();
  7. ~gralic();
  8. public:
  9. void peelinggralic();
  10. };
  11. #endif // GRALIC_H
  1. #include <iostream>
  2. #include "gralic.h"
  3. gralic::gralic()
  4. {
  5. }
  6. gralic::~gralic()
  7. {
  8. }
  9. void gralic::peelinggralic()
  10. {
  11. std::cout << "开始剥蒜啦!!!" << std::endl;
  12. }

下面是拉面类实现,只实现拉面动作即可。

  1. #ifndef NOODLE_H
  2. #define NOODLE_H
  3. class noodle
  4. {
  5. public:
  6. noodle();
  7. ~noodle();
  8. public:
  9. void makenoodle();
  10. };
  11. #endif // NOODLE_H
  1. #include <iostream>
  2. #include "noodle.h"
  3. noodle::noodle()
  4. {
  5. }
  6. noodle::~noodle()
  7. {
  8. }
  9. void noodle::makenoodle()
  10. {
  11. std::cout << "开始拉面啦!!!" << std::endl;
  12. }

其余子系统类似,就不在此展示了,包括:做汤底类和制作辣根类。
下面是外观模式,厨师师傅类,包含两个接口:制作海参炒面和辣根汤面。但是实现部分是使用各个子系统中的类和接口完成的,完成了客户端调用的解耦动作。

  1. #ifndef COOKERFACADE_H
  2. #define COOKERFACADE_H
  3. class gralic;
  4. class noodle;
  5. class soup;
  6. class lagen;
  7. class cookerfacade
  8. {
  9. public:
  10. cookerfacade();
  11. ~cookerfacade();
  12. public:
  13. void makehaishennoodle();
  14. void makelagennoodle();
  15. private:
  16. gralic *m_gra;
  17. noodle *m_noo;
  18. soup *m_so;
  19. lagen *m_lg;
  20. };
  21. #endif // COOKERFACADE_H
  1. #include <iostream>
  2. #include "cookerfacade.h"
  3. #include "gralic.h"
  4. #include "noodle.h"
  5. #include "soup.h"
  6. #include "lagen.h"
  7. cookerfacade::cookerfacade()
  8. {
  9. m_gra = new gralic();
  10. m_noo = new noodle();
  11. m_so = new soup();
  12. m_lg = new lagen();
  13. }
  14. cookerfacade::~cookerfacade()
  15. {
  16. delete m_gra; m_gra = NULL;
  17. delete m_noo; m_noo = NULL;
  18. delete m_so; m_so = NULL;
  19. delete m_lg; m_lg = NULL;
  20. }
  21. void cookerfacade::makehaishennoodle()
  22. {
  23. m_gra->peelinggralic();
  24. m_noo->makenoodle();
  25. m_so->makesoup();
  26. std::cout << "开始做海参炒面啦!!!" << std::endl;
  27. }
  28. void cookerfacade::makelagennoodle()
  29. {
  30. m_lg->makelagen();
  31. std::cout << "开始作辣根汤面啦!!!" << std::endl;
  32. }

下面是客户端代码,可以很明显的看出他只需要知道外观师傅的类即可,别的细节并不需要知道。

  1. #include <iostream>
  2. #include "cookerfacade.h"
  3. using namespace std;
  4. int main()
  5. {
  6. cookerfacade *cf = new cookerfacade();
  7. cout << "老板,来一份辣根汤面!!!" << endl;
  8. cf->makelagennoodle();
  9. cout << "老板,换一份海参炒面!!!" << endl;
  10. cf->makehaishennoodle();
  11. return 0;
  12. }

下面是编译需要的CMakeLists.txt文件:

  1. cmake_minimum_required(VERSION 2.8)
  2. project(cooker-facade)
  3. set(SRC_LIST main.cpp soup.h soup.cpp gralic.h gralic.cpp cookerfacade.h cookerfacade.cpp noodle.h noodle.cpp
  4. lagen.h lagen.cpp)
  5. add_executable(${PROJECT_NAME} ${SRC_LIST})

编译运行结果

外观模式的源代码下载位置是:https://github.com/erguangqiang/freesir_headfirst/blob/master/cooker-facade.tar.gz
代码运行的结果如下:

  1. blog@blog-VirtualBox:~/build-cooker-facade-unknown-Default$ ./cooker-facade
  2. 老板,来一份辣根汤面!!!
  3. 开始制作辣根!!!
  4. 开始作辣根汤面啦!!!
  5. 老板,换一份海参炒面!!!
  6. 开始剥蒜啦!!!
  7. 开始拉面啦!!!
  8. 开始做汤底啦!!!
  9. 开始做海参炒面啦!!!

结束语

其实外观模式我们可能一直在用,只是我们不知道自己在用外观模式而已,平时我们开发一个系统的时候,对外API完全封装内部子系统接口,以达到便于扩展可维护的目的,其实用的就是外观模式。这种模式可以充分解耦客户端和子系统。同时也是应用比较广比较简单的设计模式。

原文链接:http://www.cnblogs.com/freeman2012/p/11211362.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号