设计模式——外观模式
本篇博文通过学习尚硅谷韩顺平老师《设计模式》课程所做,在此非常感谢!
概述
基本介绍
- 外观模式(Facade),也叫“过程模式\门面模式:外观模式为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用;
- *外观模式通过定义一个一致的接口,用以屏蔽内部子系统的细节,使得调用端只需跟这个接口发生调用,而无需关心这个子系统的内部细节;
细节和注意事项
- 模式对外屏蔽了子系统的细节,因此外观模式降低了客户端对子系统使用的复杂性;
- 外观模式对客户端与子系统的耦合关系 - 解耦,让子系统内部的模块更易维护和扩展;
- 通过合理的使用外观模式,可以帮我们更好的划分访问的层次;
- 在维护一个遗留的大型系统时,可能这个系统已经变得非常难以维护和扩展,此时可以考虑为新系统开发一个Facade 类,来提供遗留系统的比较清晰简单的接口,让新系统与 Facade 类交互,提高复用性;
- 能过多的或者不合理的使用外观模式,使用外观模式好、还是直接调用模块好要通过实际需求来决定。要以让系统有层次,利于维护为目的。
UML
问题引入
组建一个家庭影院:DVD 播放器、投影仪、自动屏幕、环绕立体声、爆米花机,要求完成使用家庭影院的功能,其过程为: 一、(开爆米花机、放下屏幕、打开投影仪、打开音响)
——> 二、(暂停播放)
——> 三、(去拿爆米花、调暗灯光、继续播放DVD)
——> 四、(观影结束后,关闭各种设备)
要求使用外观模式实现上述的需求,保证客户端调用足够简单;
编码实现
UML
首先我们构造出UML
图,如下所示:
编码
首先创建我们所有需要使用的系统类
,如灯光类
、DVD 类
、爆米花机类
等,如下所示:
package edu.hebeu.appearance.childsys;
public class DVDPlayer {
private static DVDPlayer instance = new DVDPlayer();
private DVDPlayer() {}
public static DVDPlayer getInstance() {
return instance;
}
public void on() {
System.out.println("DVD开启...");
}
public void off() {
System.out.println("DVD关闭");
}
public void play() {
System.out.println("DVD正在播放...");
}
public void pause() {
System.out.println("DVD暂停");
}
public void set() {
System.out.println("DVD选择节目...");
}
// ......
}
package edu.hebeu.appearance.childsys;
public class Light {
private static Light instance = new Light();
private Light() {}
public static Light getInstance() {
return instance;
}
public void on() {
System.out.println("灯光打开...");
}
public void off() {
System.out.println("灯光关闭");
}
public void dim() {
System.out.println("灯光调暗...");
}
public void bright() {
System.out.println("灯光调亮...");
}
// ......
}
package edu.hebeu.appearance.childsys;
public class Popcorn {
private static Popcorn instance = new Popcorn();
private Popcorn() {}
public static Popcorn getInstance() {
return instance;
}
public void on() {
System.out.println("爆米花机打开...");
}
public void off() {
System.out.println("爆米花机关闭");
}
public void pop() {
System.out.println("爆米花机正在出爆米花...");
}
// ......
}
package edu.hebeu.appearance.childsys;
public class Projector {
private static Projector instance = new Projector();
private Projector() {}
public static Projector getInstance() {
return instance;
}
public void on() {
System.out.println("投影仪打开...");
}
public void off() {
System.out.println("投影仪关闭");
}
public void fox() {
System.out.println("投影仪正在聚焦...");
}
// ......
}
package edu.hebeu.appearance.childsys;
public class Screen {
private static Screen instance = new Screen();
private Screen() {}
public static Screen getInstance() {
return instance;
}
public void up() {
System.out.println("屏幕收起");
}
public void down() {
System.out.println("屏幕放下");
}
// ......
}
package edu.hebeu.appearance.childsys;
public class Stereo {
private static Stereo instance = new Stereo();
private Stereo() {}
public static Stereo getInstance() {
return instance;
}
public void on() {
System.out.println("立体声打开...");
}
public void off() {
System.out.println("立体声关闭");
}
public void up() {
System.out.println("立体声调大...");
}
public void down() {
System.out.println("立体声调小...");
}
// ......
}
此时所有的系统类
就创建完毕了,之后我们创建本模式中的外观类
,用来给使用方提供统一的接口,抽取特定的方法,为使用方屏蔽掉内部复杂的细节
package edu.hebeu.appearance;
import edu.hebeu.appearance.childsys.DVDPlayer;
import edu.hebeu.appearance.childsys.Light;
import edu.hebeu.appearance.childsys.Popcorn;
import edu.hebeu.appearance.childsys.Projector;
import edu.hebeu.appearance.childsys.Screen;
import edu.hebeu.appearance.childsys.Stereo;
public class HomeAppearance {
private DVDPlayer dvdPlayer;
private Popcorn popcorn;
private Projector projector;
private Screen screen;
private Stereo stereo;
private Light light;
public HomeAppearance() {
dvdPlayer = DVDPlayer.getInstance();
popcorn = Popcorn.getInstance();
projector = Projector.getInstance();
screen = Screen.getInstance();
stereo = Stereo.getInstance();
light = Light.getInstance();
}
public void ready() {
popcorn.on();
screen.down();
projector.on();
stereo.on();
dvdPlayer.on();
dvdPlayer.set();
}
public void off() {
dvdPlayer.off();
popcorn.off();
projector.off();
screen.up();
stereo.off();
light.off();
}
public void play() {
popcorn.pop();
light.on();
light.dim();
dvdPlayer.play();
}
public void pause() {
dvdPlayer.pause();
}
}
此时,外观模式的搭建就完成了,我们可以通过如下的测试类进行调用测试
package edu.hebeu.appearance;
public class Client {
public static void main(String[] args) throws InterruptedException {
HomeAppearance homeAppearance = new HomeAppearance();
homeAppearance.ready();
System.out.println(); System.out.println();
Thread.sleep(1500);
homeAppearance.pause();
System.out.println(); System.out.println();
Thread.sleep(1500);
homeAppearance.play();
System.out.println(); System.out.println();
Thread.sleep(2000);
homeAppearance.off();
}
}