门面模式
定义
门面模式(Façade Pattern)又称为外观模式,是一种比较常用的封装模式。
要求一个子系统的外部与其内部的通信通过一个统一的对象进行。门面模式提供一个高层次的接口,使得子系统更易于使用
优缺点、应用场景
优点
- 减少系统的相互依赖。假设非门面模式,外部系统可以直接深入子系统,之间产生强耦合关系,不符合低耦合的思想。而门面模式可以让门面对象对接外部系统,而无关子系统。
- 提高灵活性。无论子系统怎么变化,门面都是独立的。
- 提高安全性。外部系统只能访问门面提供的方法,不会直接对接子系统。
缺点
不符合开闭原则,对修改关闭、对拓展开放,一旦门面对象出现问题,只能修改门面对象的代码,风险相当大,设计时需要慎重考虑
应用场景
- 为一个复杂的模块或子系统提供一个供外界访问的接口
- 子系统相对独立,外界不关心子系统的实现
- 降低低水平开发人员带来的风险。可以指定其只能在子系统中开发,再通过门面接口进行操作
代码场景模拟
信件邮递,没有门面服务时只能自己做,使用门面模式添加一个邮局对象只需要必要信息就可以邮递,之后还可以引入检查对象对邮件信息进行检查
门面模式
UML图
写邮件需求的接口与实现
/**
* 写信告诉我今夜你想要梦什么
*/
public interface ILetterProcess {
/**
* 写信的内容
*
* @param context 信的内容
*/
void writeContext(String context);
/**
* 写信的信封
*
* @param address 地址
*/
void fillEnvelope(String address);
/**
* 把信放入信箱
*/
void letterIntoEnvelope();
/**
* 邮递
*/
void sendLetter();
}
public class LetterProcessImpl implements ILetterProcess {
@Override
public void writeContext(String context) {
System.out.println("写信的内容:" + context + "...");
}
@Override
public void fillEnvelope(String address) {
System.out.println("填写收件人姓名和地址:" + address + "...");
}
@Override
public void letterIntoEnvelope() {
System.out.println("把信放入信封中...");
}
@Override
public void sendLetter() {
System.out.println("邮递信件...");
}
}
门面对象——邮局
/**
* 暗黑功德箱邮局
*/
public class DarkMeritPostOffice {
private final ILetterProcess letterProcess = new LetterProcessImpl();
private final Police police = new Police();
/**
* 只获取写信人的必要信息
*
* @param context 信的内容
* @param address 收件人地址
*/
public void sendLetter(String context, String address) {
System.out.println("***** 暗黑功德箱邮箱让寄信更简单 *****");
// 开始写信
letterProcess.writeContext("Do you like what you see?");
// 写信封
letterProcess.fillEnvelope("Boy next door.");
// 信件检查
police.checkLetter(letterProcess);
// 把信封放到信封内,封装
letterProcess.letterIntoEnvelope();
// 投递信件给邮局
letterProcess.sendLetter();
}
}
检查对象——拓展门面的功能
/**
* 信件检查类
*/
public class Police {
/**
* 信件检查
*
* @param letterProcess 被检查的信件
*/
public void checkLetter(ILetterProcess letterProcess) {
System.out.println(letterProcess + " 已经检查过了...");
}
}
入口类
public class FacadePatternMain {
public static void main(String[] args) {
// originWriteLetter();
facadeWriteLetter();
}
/**
* 使用门面对象帮忙完成邮递过程
*/
private static void facadeWriteLetter() {
// 暗黑功德箱邮局,为你发送邮件
DarkMeritPostOffice darkMeritPostOffice = new DarkMeritPostOffice();
// 信的内容
String context = "Do you like what you see?";
// 收件人地址
String address = "Next door.";
darkMeritPostOffice.sendLetter(context, address);
}
/**
* 一般的写信流程
*/
private static void originWriteLetter() {
ILetterProcess letterProcess = new LetterProcessImpl();
// 开始写信
letterProcess.writeContext("Do you like what you see?");
// 写信封
letterProcess.fillEnvelope("Next door.");
// 把信封放到信封内,封装
letterProcess.letterIntoEnvelope();
// 投递信件给邮局
letterProcess.sendLetter();
}
}
结果
非门面模式
门面模式
参考书籍
秦小波《设计模式之禅》