《Head First 设计模式》:外观模式
正文
一、定义
外观模式提供了一个统一的接口,用来访问子系统中的一群接口。外观定义了一个高层接口,让子系统更容易使用。
要点:
- 外观模式将一个或数个类的复杂的一切都隐藏在背后,只显露出一个干净美好的外观。
- 通过将子系统的方法封装到外观的方法中,可以达到对子系统的“一键操作”。
- 外观模式的意图是简化接口,好让一个子系统更易于使用。
- 外观模式将客户从组件的子系统中解耦。
二、实现步骤
1、创建子系统组件类
(1)子系统组件A
/**
 * 子系统组件A
 */
public class ComponentA {
    public void action() {
        System.out.println("ComponentA action...");
    }
}
(2)子系统组件B
/**
 * 子系统组件B
 */
public class ComponentB {
    public void action() {
        System.out.println("ComponentB action...");
    }
}
(3)子系统组件C
/**
 * 子系统组件C
 */
public class ComponentC {
    public void action() {
        System.out.println("ComponentC action...");
    }
}
2、创建外观类
外观类的方法封装了子系统组件的一系列方法。这样,客户就可以通过外观类的方法,来一次性调用一系列子系统组件的方法。而不是一个个去调用子系统组件的方法。
/**
 * 外观类
 */
public class Facade {
    ComponentA componentA;
    ComponentB componentB;
    ComponentC componentC;
    public Facade(ComponentA componentA,
            ComponentB componentB,
            ComponentC componentC) {
        this.componentA = componentA;
        this.componentB = componentB;
        this.componentC = componentC;
    }
    /**
     * 通过外观类,请求子系统组件
     */
    public void request() {
        componentA.action();
        componentB.action();
        componentC.action();
    }
}
3、使用外观访问子系统组件
public class Test {
    public static void main(String[] args) {
        // 子系统组件
        ComponentA componentA = new ComponentA();
        ComponentB componentB = new ComponentB();
        ComponentC componentC = new ComponentC();
        // 外观类
        Facade facade = new Facade(componentA, componentB, componentC);
        facade.request();
    }
}
三、举个栗子
1、背景
假设你打算建立自己的家庭影院,通过一番研究比较,你组装了一套杀手级的系统,内含 DVD 播放器、投影机、自动屏幕、环绕立体声,甚至还有爆米花机。
你花了几个星期布线、挂上投影机、连接所有的装置并进行微调。现在你打算播放一部 DVD 影片放松一下。
但是你发现,在看电影前,必须先进行一系列操作:打开爆米花机 -> 开始爆米花 -> 将灯光调暗 -> 放下屏幕 -> 打开投影机 -> 将投影机的输入切换到 DVD -> 将投影机设置在宽屏模式 -> 打开功放 -> 将功放的输入设置为 DVD -> 将功放设置为环绕立体声 -> 将功放音量调到中(5) -> 打开 DVD 播放器 -> 开始播放 DVD。
不仅如此,看完电影后,你还要把一切都关掉。使用你的家庭影院竟变得如此复杂!于是你决定升级你的系统……
2、实现
使用外观模式将看电影相关的一系列操作,封装到外观的 watchMovie() 方法中。这样一来,要看电影的时候,只需要进行一个“看电影”的操作就行了。同理,可将看完电影相关的一系列操作,封装到 endMovie() 方法中。
(1)创建家庭影院子系统组件
/**
 * 功放
 */
public class Amplifier {
    /**
     * 打开功放
     */
    public void on() {
        System.out.println("Top-O-Line Amplifier on");
    }
    /**
     * 关闭功放
     */
    public void off() {
        System.out.println("Top-O-Line Amplifier off");
    }
    /**
     * 设置DVD
     */
    public void setDvd(DvdPlayer dvd) {
        System.out.println("Top-O-Line Amplifier setting DVD player to Top-O-Line DVD Player");
    }
    /**
     * 设置为环绕立体声
     */
    public void setSurroundSound() {
        System.out.println("Top-O-Line Amplifier surround sound on (5 speakers, 1 subwoofer)");
    }
    /**
     * 调节音量
     */
    public void setVolume(int volume) {
        System.out.println("Top-O-Line Amplifier setting volume to " + volume);
    }
}
/**
 * DVD播放器
 */
public class DvdPlayer {
    /**
     * 打开DVD播放器
     */
    public void on() {
        System.out.println("Top-O-Line DVD Player on");
    }
    /**
     * 关闭DVD播放器
     */
    public void off() {
        System.out.println("Top-O-Line DVD Player off");
    }
    /**
     * 播放DVD
     */
    public void play(String movie) {
        System.out.println("Top-O-Line DVD Player playing “" + movie + "”");
    }
    /**
     * 停止播放DVD
     */
    public void stop() {
        System.out.println("Top-O-Line DVD Player stop");
    }
    /**
     * 弹出DVD
     */
    public void eject() {
        System.out.println("Top-O-Line DVD Player eject");
    }
}
/**
 * 投影仪
 */
public class Projector {
    /**
     * 打开投影仪
     */
    public void on() {
        System.out.println("Top-O-Line Projector on");
    }
    /**
     * 关闭投影仪
     */
    public void off() {
        System.out.println("Top-O-Line Projector off");
    }
    /**
     * 设为宽屏模式
     */
    public void wideScreenMode() {
        System.out.println("Top-O-Line Projector in widescreen mode (16x9 aspect ratio)");
    }
}
/**
 * 影院灯光
 */
public class TheaterLights {
    /**
     * 打开灯光
     */
    public void on() {
        System.out.println("Theater Ceiling Lights on");
    }
    /**
     * 调暗灯光
     */
    public void dim(int level) {
        System.out.println("Theater Ceiling Lights dimming to " + level + "%");
    }
}
/**
 * 屏幕
 */
public class Screen {
    /**
     * 放下屏幕
     */
    public void down() {
        System.out.println("Theater Screen going down");
    }
    /**
     * 升起屏幕
     */
    public void up() {
        System.out.println("Theater Screen going up");
    }
}
/**
 * 爆米花机
 */
public class PopcornPopper {
    /**
     * 打开爆米花机
     */
    public void on() {
        System.out.println("Popcorn Popper on");
    }
    /**
     * 关闭爆米花机
     */
    public void off() {
        System.out.println("Popcorn Popper off");
    }
    /**
     * 开始爆米花
     */
    public void pop() {
        System.out.println("Popcorn Popper popping popcorn!");
    }
}
(2)创建家庭影院外观
/**
 * 家庭影院外观
 */
public class HomeTheaterFacade {
    Amplifier amp;
    DvdPlayer dvd;
    Projector projector;
    TheaterLights lights;
    Screen screen;
    PopcornPopper popper;
    public HomeTheaterFacade(Amplifier amp,
            DvdPlayer dvd,
            Projector projector,
            TheaterLights lights,
            Screen screen,
            PopcornPopper popper) {
        this.amp = amp;
        this.dvd = dvd;
        this.projector = projector;
        this.lights = lights;
        this.screen = screen;
        this.popper = popper;
    }
    /**
     * 看电影
     */
    public void watchMovie(String movie) {
        System.out.println("Get ready to watch a movie...");
        popper.on();
        popper.pop();
        lights.dim(10);
        screen.down();
        projector.on();
        projector.wideScreenMode();
        amp.on();
        amp.setDvd(dvd);
        amp.setSurroundSound();
        amp.setVolume(5);
        dvd.on();
        dvd.play(movie);
    }
    /**
     * 看完电影
     */
    public void endMovie() {
        System.out.println("Shuting movie theater down...");
        popper.off();
        lights.on();
        screen.up();
        projector.off();
        amp.off();
        dvd.stop();
        dvd.eject();
        dvd.off();
    }
}
(3)使用家庭影院外观观看电影
public class Test {
    public static void main(String[] args) {
        // 子系统组件
        Amplifier amp = new Amplifier();
        DvdPlayer dvd = new DvdPlayer();
        Projector projector = new Projector();
        TheaterLights lights = new TheaterLights();
        Screen screen = new Screen();
        PopcornPopper popper = new PopcornPopper();
        // 家庭影院外观
        HomeTheaterFacade homeTheater = new HomeTheaterFacade(amp, dvd, projector, lights, screen, popper);
        // 看电影
        homeTheater.watchMovie("Raiders of the Lost Ark");
        // 看完电影
        homeTheater.endMovie();
    }
}
《Head First 设计模式》:外观模式的更多相关文章
- java设计模式——外观模式(门面模式)
		一. 定义与类型 定义:门面模式,提供一个统一的接口,用来访问子系统中的一群接口,门面模式定义了一个高层接口,让子系统更容易使用 类型:结构性 二. 使用场景 子系统越来越复杂,增加外观模式提供简单调 ... 
- Java设计模式——外观模式
		JAVA 设计模式 外观模式 用途 外观模式 (Facade) 为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用. 外观模式是一种结构型模式. 结构 
- 浅谈Python设计模式 - 外观模式
		声明:本系列文章主要参考<精通Python设计模式>一书,并且参考一些资料,结合自己的一些看法来总结而来. 外观模式 外观模式的核心在于将复杂的内部实现包装起来,只向外界提供简单的调用接口 ... 
- 【设计模式】Java设计模式 - 外观模式
		Java设计模式 - 外观模式 不断学习才是王道 继续踏上学习之路,学之分享笔记 总有一天我也能像各位大佬一样 原创作品,更多关注我CSDN: 一个有梦有戏的人 准备将博客园.CSDN一起记录分享自己 ... 
- C#设计模式-外观模式
		在软件开发过程中,客户端程序经常会与复杂系统的内部子系统进行耦合,从而导致客户端程序随着子系统的变化而变化,然而为了将复杂系统的内部子系统与客户端之间的依赖解耦,从而就有了外观模式,也称作 ”门面“模 ... 
- [Head First设计模式]生活中学设计模式——外观模式
		系列文章 [Head First设计模式]山西面馆中的设计模式——装饰者模式 [Head First设计模式]山西面馆中的设计模式——观察者模式 [Head First设计模式]山西面馆中的设计模式— ... 
- JAVA 设计模式 外观模式
		用途 外观模式 (Facade) 为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用. 外观模式是一种结构型模式. 结构 
- Java设计模式---外观模式
		外观模式(Facade) 外观模式的意图是:为子系统提供一个接口,便于它的使用. 解释: 简单的说,外观模式就是封装多个上层应用需要的方法,使得上层调用变得简单,为上层提供简单的接口,是设计模式中 ... 
- 设计模式——外观模式(Facade)
		1. 概述 外观模式,我们通过外观的包装,使应用程序只能看到外观对象,而不会看到具体的细节对象,这样无疑会降低应用程序的复杂度,并且提高了程序的可维护性. 例子1:一个电源总开关可以控制四盏灯 ... 
- 设计模式 | 外观模式/门面模式(facade)
		定义: 为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用. 结构:(书中图,侵删) 一个简洁易用的外观类 一个复杂的子系统 实例: 书中提到了理 ... 
随机推荐
- Python自动化运维:技术与最佳实践 PDF高清完整版|网盘下载内附地址提取码|
			内容简介: <Python自动化运维:技术与最佳实践>一书在中国运维领域将有“划时代”的重要意义:一方面,这是国内第一本从纵.深和实践角度探讨Python在运维领域应用的著作:一方面本书的 ... 
- PHP array_intersect_uassoc() 函数
			实例 比较两个数组的键名和键值(使用用户自定义函数比较键名),并返回交集: <?phpfunction myfunction($a,$b){if ($a===$b){return 0;}retu ... 
- Python os.chflags() 方法
			概述 os.chflags() 方法用于设置路径的标记为数字标记.多个标记可以使用 OR 来组合起来.高佣联盟 www.cgewang.com 只支持在 Unix 下使用. 语法 chflags()方 ... 
- PHP preg_match_all() 函数
			preg_match_all 函数用于执行一个全局正则表达式匹配.高佣联盟 www.cgewang.com 语法 int preg_match_all ( string $pattern , stri ... 
- PHP str_ireplace() 函数
			实例 把字符串 "Hello world!" 中的字符 "WORLD"(不区分大小写)替换成 "Peter": <?php高佣联盟 w ... 
- 转载——完整的ASCII码表
			完整的ASCII码表,转载自下面的博主: http://www.cnblogs.com/xmxu/archive/2012/07/10/2584032.html 
- mit-6.828 Lab Tools
			Lab Tools 目录 Lab Tools 写在前面 GDB GNU GPL (通用公共许可证) QEMU ELF 可执行文件的格式 Verbose mode Makefile 写在前面 操作系统小 ... 
- day12. 闭包
			一.概念 """ 如果内函数使用了外函数的局部变量, 并且外函数把内函数返回出来的过程,叫做闭包 里面的内函数是闭包函数 """ 二.基本语 ... 
- Ef Core增加Sql方法
			[AttributeUsage(AttributeTargets.Class|AttributeTargets.Method)] public class DbFunAttribute : Attri ... 
- Tarjan算法 学习笔记
			前排提示:先学习拓扑排序,再学习Tarjan有奇效. -------------------------- Tarjan算法一般用于有向图里强连通分量的缩点. 强连通分量:有向图里能够互相到达的点的集 ... 
