设计模式之Facade设计模式

2024-07-09 1178阅读

Facade设计模式,也称为外观模式,是一种结构型设计模式,它主要用于为子系统中的一组接口提供一个统一的高层接口,从而使得子系统更加容易使用。以下是关于Facade设计模式的详细介绍:

一、定义

Facade模式为多个复杂的子系统提供一个对外的接口,使得这些子系统更加容易地被访问。该模式对外有一个统一的接口,外部应用无需关心子系统内部的细节,从而大大降低了应用程序的复杂度,提高了可维护性。

二、动机与目的

  • 降低复杂性:通过将子系统的复杂性封装在Facade类中,客户端可以通过简单的接口来调用子系统,而无需深入了解子系统的具体实现。
  • 提高易用性:Facade模式提供了一个简单的接口,使得客户端可以更容易地使用子系统。
  • 松散耦合:通过引入Facade类,降低了客户端与子系统之间的耦合度,使得子系统内部的变化不会影响到客户端。

    三、结构与类图

    类图:

    设计模式之Facade设计模式

    Facade模式主要包含以下三个角色:

    • Facade(外观角色):客户端可以调用这个角色的方法。外观类知晓相关的(一个或者多个)子系统的功能和责任。在正常情况下,本角色会将所有从客户端发来的请求委派到相应的子系统去。
    • Subsystem(子系统角色):可以同时有一个或者多个子系统。每一个子系统都不是一个单独的类,而是一个类的集合。每一个子系统都可以被客户端直接调用,或者被外观角色调用。子系统并不知道外观的存在,对于子系统而言,外观仅仅是另外一个客户端而已。
    • Client(客户端角色):用户通过外观类调用子系统的功能。

      四、优缺点

      优点
      1. 降低系统的复杂性:通过为子系统提供一个简单的接口,使得客户端更容易理解和使用系统。
      2. 提高系统的灵活性:当子系统内部发生变化时,只需要修改Facade类即可,而不需要修改客户端代码。
      3. 符合迪米特法则:通过引入Facade类,减少了客户端与子系统之间的依赖关系。
      缺点
      1. 增加子系统或扩展子系统行为容易引入风险:因为所有的请求都需要通过Facade类进行转发,如果Facade类设计不当,可能会引入新的风险。
      2. 不符合开闭原则:在某些情况下,如果需要对系统进行扩展,可能需要修改Facade类的代码,这违反了开闭原则(即对扩展开放,对修改关闭)。

      五、应用场景

      • 当系统需要对外提供一个简单的接口时,可以使用Facade模式。
      • 当系统需要隐藏子系统的复杂性时,可以使用Facade模式。
      • 当需要构建一个多层系统结构时,可以利用Facade对象作为每层的入口,简化层级调用。

        六、实现例子

        在家庭影院系统中,可以使用Facade模式来简化用户的操作。例如,用户只需要使用一个遥控器(Facade类)就可以控制投影仪、音响、DVD机等设备(子系统),而无需分别操作这些设备。

        // 投影仪接口  
        interface Projector {  
            void on();  
            void off();  
            void focus();  
            void wideScreenMode();  
        }  
          
        // 投影仪实现类  
        class SimpleProjector implements Projector {  
            @Override  
            public void on() {  
                System.out.println("Projector is on");  
            }  
          
            @Override  
            public void off() {  
                System.out.println("Projector is off");  
            }  
          
            @Override  
            public void focus() {  
                System.out.println("Adjusting projector focus");  
            }  
          
            @Override  
            public void wideScreenMode() {  
                System.out.println("Switching to wide screen mode");  
            }  
        }  
          
        // DVD播放器接口  
        interface DVDPlayer {  
            void on();  
            void off();  
            void play();  
            void stop();  
            void pause();  
            void eject();  
            void setTwoChannelAudio();  
            void setSurroundAudio();  
        }  
          
        // DVD播放器实现类  
        class SimpleDVDPlayer implements DVDPlayer {  
            @Override  
            public void on() {  
                System.out.println("DVD Player is on");  
            }  
          
            @Override  
            public void off() {  
                System.out.println("DVD Player is off");  
            }  
          
            @Override  
            public void play() {  
                System.out.println("DVD Player is playing");  
            }  
          
            @Override  
            public void stop() {  
                System.out.println("DVD Player stopped");  
            }  
          
            @Override  
            public void pause() {  
                System.out.println("DVD Player paused");  
            }  
          
            @Override  
            public void eject() {  
                System.out.println("DVD ejected");  
            }  
          
            @Override  
            public void setTwoChannelAudio() {  
                System.out.println("Stereo mode is on");  
            }  
          
            @Override  
            public void setSurroundAudio() {  
                System.out.println("Surround sound mode is on");  
            }  
        }  
          
        // 音响接口  
        interface Amplifier {  
            void on();  
            void off();  
            void setStereoSound();  
            void setSurroundSound();  
            void setVolume(int volume);  
        }  
          
        // 音响实现类  
        class StereoAmplifier implements Amplifier {  
            @Override  
            public void on() {  
                System.out.println("Amplifier is on");  
            }  
          
            @Override  
            public void off() {  
                System.out.println("Amplifier is off");  
            }  
          
            @Override  
            public void setStereoSound() {  
                System.out.println("Stereo mode is on");  
            }  
          
            @Override  
            public void setSurroundSound() {  
                System.out.println("Surround sound mode is on");  
            }  
          
            @Override  
            public void setVolume(int volume) {  
                System.out.println("Setting volume to " + volume);  
            }  
        }  
          
        // 家庭影院Facade类  
        class HomeTheaterFacade {  
            private Projector projector;  
            private DVDPlayer dvdPlayer;  
            private Amplifier amplifier;  
          
            public HomeTheaterFacade(Projector projector, DVDPlayer dvdPlayer, Amplifier amplifier) {  
                this.projector = projector;  
                this.dvdPlayer = dvdPlayer;  
                this.amplifier = amplifier;  
            }  
          
            // 提供一个简单的方法来观看电影  
            public void watchMovie(String movie) {  
                System.out.println("Get ready to watch a movie...");  
          
                projector.on();  
                projector.wideScreenMode();  
          
                amplifier.on();  
                amplifier.setSurroundSound();  
                amplifier.setVolume(5);  
          
                dvdPlayer.on();  
                dvdPlayer.play(movie);  
          
                System.out.println("Enjoy the movie...");  
            }  
          
            // 提供一个简单的方法来结束观看  
            public void endMovie() {  
                System.out.println("Shutting movie theater down...");  
          
                projector.off();  
                amplifier.off();  
                dvdPlayer.stop();  
                dvdPlayer.eject();  
                dvdPlayer.off();
            }
        }
                
        class Client{
            public static void main(String[] args) { 
                Projector projector = new SimpleProjector();
                DVDPlayer dvdPlayer = new SimpleDVDPlayer();
                Amplifier amplifier = new StereoAmplifier();
                HomeTheaterFacade homeTheaterFacade = new HomeTheaterFacade(projector,dvdPlayer,amplifier);
                homeTheaterFacade.watchMovie("肖申克的救赎");
                homeTheaterFacade.endMovie();
            }
        }

        这个例子中可以看到facade模式,特别适用于使用多个组件,组装固定流程,降低客户端的调用复杂度。

        七、总结

        Facade设计模式是一种非常实用的设计模式,它通过为子系统提供一个统一的接口来降低系统的复杂性、提高系统的易用性和灵活性。然而,在使用该模式时也需要注意其可能带来的缺点和风险。

        如果这个模式对你有用,记得点赞收藏。

VPS购买请点击我

免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们,邮箱:ciyunidc@ciyunshuju.com。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!

目录[+]