10.java设计模式之外观模式

基本需求

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

传统方案

  • 客户端直接依赖各种设备,直接调用各种设备的方法
  • UML类图
  • 在Client中,创建各个子系统的对象,并直接去调用子系统(对象)相关方法,会造成调用过程混乱,没有清晰的过程,不利于维护
  • 定义一个高层接口,给子系统中的一组接口提供一个一致的界面(比如在高层接口提供四个方法ready, play, pause, end),用来访问子系统中的一群接口,就是通过定义一个一致的接口(界面类),用以屏蔽内部子系统的细节,使得调用端只需跟这个接口发生调用,而无需关心这个子系统的内部细节 -> 外观模式

基本介绍

  • 外观模式(Facade)隐藏系统的复杂性,并向客户端提供了一个客户端可以访问系统的接口。这种类型的设计模式属于结构型模式,它向现有的系统添加一个接口,来隐藏系统的复杂性。这种模式涉及到一个单一的类,该类提供了客户端请求的简化方法和对现有系统类方法的委托调用

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

  • 主要解决:降低访问复杂系统的内部子系统时的复杂度,简化客户端与之的接口

  • UMl类图(原理)

    • Facade类为外观类,聚合了其他多个子系统(实际功能的提供者),让client统一调用
  • UML类图(案例)

  • 代码实现

    • public class DVDPlayer {
      
         // DVD播放器 使用饿汉
         public static final DVDPlayer DVD_PLAYER = new DVDPlayer();
      
         private DVDPlayer() {
         }
      
         public static DVDPlayer getInstance() {
             return DVD_PLAYER;
         }
      
         public void on() {
             System.out.println("dvd on");
         }
      
         public void off() {
             System.out.println("dvd off");
         }
      
         public void play() {
             System.out.println("dvd play");
         }
      
         public void pause() {
             System.out.println("dvd pause");
         }
      
      }
      
    • public class Screen {
      
         // 屏幕 使用饿汉
         public static final Screen SCREEN = new Screen();
      
         private Screen() {
         }
      
         public static Screen getInstance() {
             return SCREEN;
         }
      
         public void up() {
             System.out.println("screen up");
         }
      
         public void dowm() {
             System.out.println("screen down");
         }
      
      }
      
      
    • public class Popcorn {
      
         // 爆米花机 使用饿汉
         public static final Popcorn POPCORN = new Popcorn();
      
         private Popcorn() {
         }
      
         public static Popcorn getInstance() {
             return POPCORN;
         }
      
         public void on() {
             System.out.println("popcorn on");
         }
      
         public void off() {
             System.out.println("popcorn off");
         }
      
         public void pop() {
             System.out.println("popcorn pop");
         }
      
      }
      
      
    • public class Projector {
      
         // 投影仪 使用饿汉
         public static final Projector PROJECTOR = new Projector();
      
         private Projector() {
         }
      
         public static Projector getInstance() {
             return PROJECTOR;
         }
      
         public void on() {
             System.out.println("projector on");
         }
      
         public void off() {
             System.out.println("projector off");
         }
      
         public void focus() {
             System.out.println("projector focus");
         }
      
      }
      
    • public class TheaterLight {
      
         // 影院灯光 使用饿汉
         public static final TheaterLight THEATER_LIGHT = new TheaterLight();
      
         private TheaterLight() {
         }
      
         public static TheaterLight getInstance() {
             return THEATER_LIGHT;
         }
      
         public void on() {
             System.out.println("theater_light on");
         }
      
         public void off() {
             System.out.println("theater_light off");
         }
      
         public void dim() {
             System.out.println("theater_light dim");
         }
      
         public void bright() {
             System.out.println("theater_light bright");
         }
      
      }
      
    • public class Stereo {
      
         // 立体声 使用饿汉
         public static final Stereo STEREO = new Stereo();
      
         private Stereo() {
         }
      
         public static Stereo getInstance() {
             return STEREO;
         }
      
         public void on() {
             System.out.println("stereo on");
         }
      
         public void off() {
             System.out.println("stereo off");
         }
      
         public void up() {
             System.out.println("stereo up");
         }
      
      }
      
      
    • public class HomeTheaterFacade {
      
         // 影院外观类,聚合其他子系统 ,提供统一的方法供Client调用
         private DVDPlayer dvdPlayer = DVDPlayer.getInstance();
         private Screen screen = Screen.getInstance();
         private Popcorn popcorn = Popcorn.getInstance();
         private Projector projector = Projector.getInstance();
         private TheaterLight theaterLight = TheaterLight.getInstance();
         private Stereo stereo = Stereo.getInstance();
      
         public HomeTheaterFacade() {
         }
      
         // 给Client提供的方法相当于子系统方法的集合
         public void ready() {
             popcorn.on();
             popcorn.pop();
             screen.dowm();
             projector.on();
             projector.focus();
             theaterLight.on();
             stereo.on();
             dvdPlayer.on();
         }
      
         public void play() {
             theaterLight.dim();
             stereo.up();
             dvdPlayer.play();
         }
      
         public void pause() {
             dvdPlayer.pause();
         }
      
         public void end() {
             popcorn.off();
             screen.up();
             projector.off();
             theaterLight.off();
             stereo.off();
             dvdPlayer.off();
         }
      
      }
      
      
    • public class Client {
         public static void main(String[] args) {
             HomeTheaterFacade homeTheaterFacade = new HomeTheaterFacade();
             System.out.println("-----------ready-----------");
             homeTheaterFacade.ready();
             System.out.println("-----------play-----------");
             homeTheaterFacade.play();
             System.out.println("-----------pause-----------");
             homeTheaterFacade.pause();
             System.out.println("-----------end-----------");
             homeTheaterFacade.end();
         }
      }
      

mybatis源码

  • 在mybatis的configuration类中的newMetaObject方法中创建MetaObject时使用的构造方法中就用到的外观模式
  • UML类图
    • configuration类就相当于facade类

注意事项

  • 外观模式对外屏蔽了子系统的细节,因此外观模式降低了客户端对子系统使用的复杂性
  • 外观模式对客户端与子系统的耦合关系 - 解耦,让子系统内部的模块更易维护和扩展
  • 通过合理的使用外观模式,可以帮我们更好的划分访问的
  • 当系统需要进行分层设计时,可以考虑使用Facade模式(三层架构)
  • 在维护一个遗留的大型系统时,可能这个系统已经变得非常难以维护和扩展,此时可以考虑为新系统开发一个Facade类,来提供遗留系统的比较清晰简单的接口,让新系统与Facade类交互,提高复用性
  • 不能过多的或者不合理的使用外观模式,使用外观模式好,还是直接调用模块好。要以让系统有层次,利于维护为目的
posted @ 2020-11-19 19:25  xiaokantianse  阅读(97)  评论(0编辑  收藏  举报