目录
说明
- 结构型模式之一,其他还有适配器模式、桥接模式、组合模式、装饰模式、享元模式、代理模式
- 外观模式(Facade Pattern)通过定义一个一致的接口,用以屏蔽内部子系统的细节,使得调用端只需跟这个接口发生调用,而无需关心这个子系统的内部细节
目标
- 调用方只接触外观类,即可使用子模块/子系统的功能接口
-
外观模式就是解决多个复杂接口带来的使用 困难,起到简化用户操作的作用
实现方式
现在提倡智能家居,很多电子产品发挥了重要作用,例如电视机、空调、智能灯光等等。小明觉得很懒,想着开关电视机就得拿电视机的遥控器,开关空调也得用空调遥控器,开关灯也是如此。有没有一款万能遥控器,可以遥控各个家电,甚至可以一键开关多个家电的呢?当然,这就可以用外观模式(门面模式/过程模式)来实现了。
/**
* 外观模式(门面模式)(调用方只接触外观类,即可使用子模块/子系统的功能接口)
* <p>
* 以万能遥控器遥控各个电器为例
*
* @author ZRH
* @version 1.0.0
* @date 2020/7/23
*/
public class FacadeTest {
public static void main(String[] args) {
AbstractMachine airConditioner = new AirConditioner();
AbstractMachine television = new Television();
AbstractMachine light = new Light();
UniversalRemote universalRemote = new UniversalRemote(airConditioner, television, light);
// 打开
universalRemote.turnOnAirConditioner();
universalRemote.turnOnTelevisionAndLight();
// 关闭
universalRemote.turnOffAirConditioner();
universalRemote.turnOffTelevisionAndLight();
}
}
abstract class AbstractMachine {
/**
* 开启
* <p>
* @author : ZRH
* @version : 1.0.0
* @date : 2020-07-23
*/
public abstract void turnOn();
/**
* 关闭
* <p>
* @author : ZRH
* @version : 1.0.0
* @date : 2020-07-23
*/
public abstract void turnOff();
}
/**
* 空调
* <p>
*
* @author ZRH
* @version 1.0.0
* @date 2020/7/23
*/
class AirConditioner extends AbstractMachine {
/**
* 开启
* <p>
*
* @author : ZRH
* @version : 1.0.0
* @date : 2020-07-23
*/
@Override
public void turnOn() {
System.out.println("开空调");
}
/**
* 关闭
* <p>
*
* @author : ZRH
* @version : 1.0.0
* @date : 2020-07-23
*/
@Override
public void turnOff() {
System.out.println("关空调");
}
}
/**
* 电视
* <p>
*
* @author ZRH
* @version 1.0.0
* @date 2020/7/23
*/
class Television extends AbstractMachine {
/**
* 开启
* <p>
*
* @author : ZRH
* @version : 1.0.0
* @date : 2020-07-23
*/
@Override
public void turnOn() {
System.out.println("开电视");
}
/**
* 关闭
* <p>
*
* @author : ZRH
* @version : 1.0.0
* @date : 2020-07-23
*/
@Override
public void turnOff() {
System.out.println("关电视");
}
}
/**
* 灯
* <p>
*
* @author ZRH
* @version 1.0.0
* @date 2020/7/23
*/
class Light extends AbstractMachine {
/**
* 开启
* <p>
*
* @author : ZRH
* @version : 1.0.0
* @date : 2020-07-23
*/
@Override
public void turnOn() {
System.out.println("开灯");
}
/**
* 关闭
* <p>
*
* @author : ZRH
* @version : 1.0.0
* @date : 2020-07-23
*/
@Override
public void turnOff() {
System.out.println("关灯");
}
}
/**
* 万能遥控器(Facade类), 可自定义暴露的接口
* <p>
*
* @author ZRH
* @version 1.0.0
* @date 2020/7/23
*/
class UniversalRemote {
private final AbstractMachine airConditioner;
private final AbstractMachine television;
private final AbstractMachine light;
public UniversalRemote(AbstractMachine airConditioner, AbstractMachine television, AbstractMachine light) {
this.airConditioner = airConditioner;
this.television = television;
this.light = light;
}
/**
* 遥控器一键打开电视和灯(自定义暴露的接口)
* <p>
*
* @author ZRH
* @date 2020-07-23
* @version 1.0.0
*/
public void turnOnTelevisionAndLight() {
if (television == null || light == null) {
System.out.println("机器未知类型");
} else {
television.turnOn();
light.turnOn();
}
}
/**
* 遥控器一键关闭电视和灯
* <p>
*
* @author ZRH
* @date 2020-07-23
* @version 1.0.0
*/
public void turnOffTelevisionAndLight() {
if (television == null || light == null) {
System.out.println("机器未知类型");
} else {
television.turnOff();
light.turnOff();
}
}
/**
* 遥控器打开空调
* <p>
*
* @author ZRH
* @date 2020-07-23
* @version 1.0.0
*/
public void turnOnAirConditioner() {
if (airConditioner == null) {
System.out.println("机器未知类型");
} else {
airConditioner.turnOn();
}
}
/**
* 遥控器关闭空调
* <p>
*
* @author ZRH
* @date 2020-07-23
* @version 1.0.0
*/
public void turnOffAirConditioner() {
if (airConditioner == null) {
System.out.println("机器未知类型");
} else {
airConditioner.turnOff();
}
}
}
在万能遥控器类里,我们可以自行封装所需方法,要哪几种电器捆绑一起就捆绑一起。
注意事项
-
外观模式对外屏蔽了子系统的细节,降低了客户端对子系统使用的复杂性
-
当系统需要进行分层设计时,可以考虑使用 Facade 模式
-
在维护一个遗留的大型系统时,可能这个系统已经变得非常难以维护和扩展,此时可以考虑为新系统开发一个Facade 类,来提供遗留系统的比较清晰简单的接口,让新系统与Facade 类交互,提高复用性
-
不能过多的或者不合理的使用外观模式,使用外观模式好,还是直接调用模块好。要以让系统有层次,利于维护为目的