介绍
外观模式(Facade)是对象的结构模式。外部与一个子系统的通信必须通过一个统一的外观(Facade)对象进行。
外观模式(Facade)在开发过程中的运用频率非常高,尤其是在现阶段,各种第三方SDK“充斥”在我们的周边,而这些SDK大多会使用外观模式。通过一个外观类使得整个系统的接口只有一个统一的高层接口,这样能降低用户的使用成本,也对用户屏蔽了很多实现细节。当然,在我们的开发过程中,外观模式也是我们封装API的常用手段,例如网络模块、ImageLoader模块等。
模式角色
外观模式有以下角色:
- Facade(外观),为多个子系统对外提供一个共同的接口。
- Subsystem(子系统),实现系统的部分功能,客户可以通过外观角色访问它。可以同时有一个或者多个子系统,每个子系统都不是一个单独的类,而是一个类的集合。
- Client(客户端),通过一个外观角色访问各个子系统的功能。
模式结构图
(来源于网上)
模式实现
背景介绍,现有一个保安系统的例子,一个保安系统有摄像头、照射灯、传感器、警报器等…
/**
* 摄像机
*/
public interface ICamera {
// 打开Camera
void turnOn();
// 关闭Camera
void turnOff();
// 转动Camera
void rotate(int degrees);
}
public class CameraImpl implements ICamera {
@Override
public void turnOn() {
System.out.println("监控启动");
}
@Override
public void turnOff() {
System.out.println("监控关闭");
}
@Override
public void rotate(int degrees) {
System.out.println("旋转监控" + degrees);
}
}
/**
* 照射灯
*/
public interface ILight {
// 打开灯
void turnOn();
// 关闭灯
void turnOff();
// 换灯泡
void changeBulb();
}
public class LightImpl implements ILight {
@Override
public void turnOn() {
System.out.println("打开红外灯");
}
@Override
public void turnOff() {
System.out.println("关闭红外灯");
}
@Override
public void changeBulb() {
System.out.println("换灯泡");
}
}
/**
* 传感器
*/
public interface ISensor {
// 启动感应器
void activate();
// 关闭感应器
void deactivate();
// 触发感应器
void trigger();
}
public class SensorImpl implements ISensor {
@Override
public void activate() {
System.out.println("启动红外跟踪传感器");
}
@Override
public void deactivate() {
System.out.println("启动红外跟踪传感器");
}
@Override
public void trigger() {
System.out.println("触发红外跟踪传感器");
}
}
/**
* 警报器
*/
public interface IAlarm {
// 启动感应器
void activate();
// 关闭感应器
void deactivate();
// 拉响警报
void ring();
// 关闭警报器
void stopRing();
}
public class AlarmImpl implements IAlarm {
@Override
public void activate() {
System.out.println("启动报警器");
}
@Override
public void deactivate() {
System.out.println("关闭报警器");
}
@Override
public void ring() {
System.out.println("拉响警报");
}
@Override
public void stopRing() {
System.out.println("关闭报警");
}
}
未使用Facade模式
public class FacadeClient {
public static void main(String[] args) {
ICamera camera1 = new CameraImpl();
ICamera camera2 = new CameraImpl();
ILight light1 = new LightImpl();
ILight light2 = new LightImpl();
ISensor sensor = new SensorImpl();
IAlarm alarm = new AlarmImpl();
camera1.turnOn();
camera2.turnOn();
light1.turnOn();
light2.turnOn();
sensor.activate();
alarm.activate();
}
}
使用Facade模式
public class SecuritySystemFacade {
private ICamera camera1, camera2;
private ILight light1, light2;
private ISensor sensor;
private IAlarm alarm;
public SecuritySystemFacade() {
camera1 = new CameraImpl();
camera2 = new CameraImpl();
light1 = new LightImpl();
light2 = new LightImpl();
sensor = new SensorImpl();
alarm = new AlarmImpl();
}
public void activate() {
camera1.turnOn();
camera2.turnOn();
light1.turnOn();
light2.turnOn();
sensor.activate();
alarm.activate();
}
public void deactivate() {
camera1.turnOff();
camera2.turnOff();
light1.turnOff();
light2.turnOff();
sensor.deactivate();
alarm.deactivate();
}
}
public class FacadeClient {
private static final SecuritySystemFacade facade = new SecuritySystemFacade();
public static void main(String[] args) {
facade.activate();
}
}
模式使用场景
- 对分层结构系统构建时,使用外观模式定义子系统中每层的入口点可以简化子系统之间的依赖关系。
- 当一个复杂系统的子系统很多时,外观模式可以为系统设计一个简单的接口供外界访问。
- 当客户端与多个子系统之间存在很大的联系时,引入外观模式可将它们分离,从而提高子系统的独立性和可移植性。