案例

影院管理项目
组建一个家庭影院:
DVD播放器、投影仪、自动屏幕、环绕立体声、爆米花机,要求完成使用家庭影院的
功能,其过程为:
• 直接用遥控器:统筹各设备开关
• 开爆米花机
• 放下屏幕
• 开投影仪
• 开音响
• 开DVD,选dvd
• 去拿爆米花
• 调暗灯光
• 播放
• 观影结束后,关闭各种设备

传统方式

image.png

问题分析

在ClientTest的main方法中,创建各个子系统的对象,并直接去调用子系统的相关方法,会造成过程混乱,没有清晰的过程
不利于ClientTest中,去维护子系统的操作

解决思路

定义一个高层接口,给子系统中的一组接口提供一个一致的界面,(比如在高层接口提供四个方法 ready play pause end),用来访问子系统的一群接口
也就是说 通过定义一个一致的接口(界面类),用以屏蔽内部子系统细节,使得调用端只需和这个接口发生调用,而无需关系这个子系统内部细节 ===》外观模式

外观模式

外观模式,也叫做“过程模式”:外观模式为子系统中的一组接口提供一个一致的界面,厕模式定义了一个高层接口,使得这个子系统更容易使用

外观模式通过定义一个一致的接口,用以屏蔽内部子系统的细节,使得调用端只需和这个接口发生调用,而无需关系这个子系统的内部细节

类图

image.png
外观类(Facade):为调用者提供统一调用接口,外观类知道哪些子系统负责处理请求从而将调用端请求代理给适当的子系统对象

调用者(Client):外观接口调用者

子系统集合:指模块或者子系统,处理Facade对象指派的任务,它是功能那个的实际提供者

image.png

UML:
image.png

  1. public class DVDPlayer {
  2. //使用单例模式, 使用饿汉式
  3. private static DVDPlayer instance = new DVDPlayer();
  4. public static DVDPlayer getInstanc() {
  5. return instance;
  6. }
  7. public void on() {
  8. System.out.println(" dvd on ");
  9. }
  10. public void off() {
  11. System.out.println(" dvd off ");
  12. }
  13. public void play() {
  14. System.out.println(" dvd is playing ");
  15. }
  16. //....
  17. public void pause() {
  18. System.out.println(" dvd pause ..");
  19. }
  20. }
  21. public class Popcorn {
  22. private static Popcorn instance = new Popcorn();
  23. public static Popcorn getInstance() {
  24. return instance;
  25. }
  26. public void on() {
  27. System.out.println(" popcorn on ");
  28. }
  29. public void off() {
  30. System.out.println(" popcorn ff ");
  31. }
  32. public void pop() {
  33. System.out.println(" popcorn is poping ");
  34. }
  35. }
  36. public class Projector {
  37. private static Projector instance = new Projector();
  38. public static Projector getInstance() {
  39. return instance;
  40. }
  41. public void on() {
  42. System.out.println(" Projector on ");
  43. }
  44. public void off() {
  45. System.out.println(" Projector ff ");
  46. }
  47. public void focus() {
  48. System.out.println(" Projector is Projector ");
  49. }
  50. //...
  51. }
  52. ...

外观类

  1. public class HomeTheaterFacade {
  2. //定义各个子系统对象
  3. private TheaterLight theaterLight;
  4. private Popcorn popcorn;
  5. private Stereo stereo;
  6. private Projector projector;
  7. private Screen screen;
  8. private DVDPlayer dVDPlayer;
  9. //构造器
  10. public HomeTheaterFacade() {
  11. super();
  12. this.theaterLight = TheaterLight.getInstance();
  13. this.popcorn = Popcorn.getInstance();
  14. this.stereo = Stereo.getInstance();
  15. this.projector = Projector.getInstance();
  16. this.screen = Screen.getInstance();
  17. this.dVDPlayer = DVDPlayer.getInstanc();
  18. }
  19. //操作分成 4 步
  20. public void ready() {
  21. popcorn.on();
  22. popcorn.pop();
  23. screen.down();
  24. projector.on();
  25. stereo.on();
  26. dVDPlayer.on();
  27. theaterLight.dim();
  28. }
  29. public void play() {
  30. dVDPlayer.play();
  31. }
  32. public void pause() {
  33. dVDPlayer.pause();
  34. }
  35. public void end() {
  36. popcorn.off();
  37. theaterLight.bright();
  38. screen.up();
  39. projector.off();
  40. stereo.off();
  41. dVDPlayer.off();
  42. }
  43. }

测试类

  1. public static void main(String[] args) {
  2. // TODO Auto-generated method stub
  3. //这里直接调用。。 很麻烦
  4. HomeTheaterFacade homeTheaterFacade = new HomeTheaterFacade();
  5. homeTheaterFacade.ready();
  6. homeTheaterFacade.play();
  7. homeTheaterFacade.end();
  8. }

注意事项

外观模式堆外屏蔽了子系统的细节,因此外观模式降低了客户点对子系统的复杂性
外观模式将客户端和子系统解耦