门面模式【Facade Pattern】也叫外观模式,是1种比较经常使用的封装模式,其定义以下:
【要求1个子系统的外部与其内部的通讯必须通过1个统1的对象进行。门面模式提供1个高层次的接口,使得子系统更容易使用】
门面模式重视“统1的对象”,也就是提供了1个访问子系统的接口,除这个接口不允许有任何访问子系统的行动产生。
门面模式的系统类图以下:
类图就是这么简单,但是意义其实很复杂
Subsystem Classes 是所有子系统所有类的简称,它可能代表1个类,也可能代表几10个对象的集合。不管多少对象,我们都将他们化为子系统的范畴,结构如图:
【不管子系统有多麻烦,外部只能通过这个【Facade——门面对象】来进行通讯】
1般情况下,Facade会将所有从客户端发来的要求委派到相应的子系统去,也就是说该角色没有实际的 业务逻辑,是1个拜托类。
下面是门面模式的通用源码
//子系统源代码
public class ClassA{
public void doSomethingA(){
//业务逻辑
}
}
public class ClassB{
public void doSomethingB(){
//业务逻辑
}
}
public class ClassC{
public void doSomethingC(){
//业务逻辑
}
}
//门面对象
public class Facade{
//被拜托的对象
private ClassA a = new ClassA();
private ClassB b = new ClassB();
private ClassC c = new ClassC();
//提供给外部访问的方法
public void methodA(){
this.a.doSomethingA();
}
public void methodB(){
this.b.doSomethingB();
}
public void methodC(){
this.c.doSomethingC();
}
}
下面用1个例子来看1下具体的门面模式
例子:【我要投递信件】
我们都写过纸质的信件,比如给女朋友写情书甚么的。写信的进程大家应当都记得——先写信的内容,然后写信封,在把信放到信封里,封好,投递到信箱中进行投递。虽然简单,但是这4个步骤都是不可或缺的!
首先我们看如果不使用门面模式应当是怎样实现的
public interface ILetterProcess {
//首先要写信的内容
public void writeContext(String context);
//其次写信封
public void fillEnvelope(String address);
//然后邮递
public void letterInotoEnvolope();
//然后邮递
public 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 letterInotoEnvolope() {
System.out.println("把信放到信封中...");
}
@Override
public void sendLetter() {
System.out.println("邮递信件...");
}
}
public class Client {
public static void main(String[] args) {
ILetterProcess letterProcess = new LetterProcessImpl();
letterProcess.writeContext("Hello, It's me, do you know Who I am? I'm your old lover.");
letterProcess.fillEnvelope("Happy Road No. 666, God Province, Heaven");
letterProcess.letterInotoEnvolope();
letterProcess.sendLetter();
}
}
Output:
/**
填写信的内容... Hello, It's me, do you know Who I am? I'm your old lover.
填写收信人的姓名和地址...Happy Road No. 666, God Province, Heaven
把信放到信封中...
邮递信件...
*/
上面的代码与高内聚的要求相差甚远,更不说迪米特原则和接口隔离原则了。
怎样办呢?
邮局出了新的业务,你告知我信的内容和地址,其余的我帮你弄定。
加了1个邮局的类
public class ModenPostOffice {
//这就是门面对象
private ILetterProcess letterProcess = new LetterProcessImpl();
public void sendLetter(String context, String address){
letterProcess.writeContext(context);
letterProcess.fillEnvelope(address);
letterProcess.letterInotoEnvolope();
letterProcess.sendLetter();
}
}
修改场景类
public class Client {
public static void main(String[] args) {
ModenPostOffice modenPostOffice = new ModenPostOffice();
String context = "Hello, It's me, do you know Who I am? I'm your old lover.";
String address = "Happy Road No. 666, God Province, Heaven";
modenPostOffice.sendLetter(context, address);
}
}
//Output
/**
填写信的内容... Hello, It's me, do you know Who I am? I'm your old lover.
填写收信人的姓名和地址...Happy Road No. 666, God Province, Heaven
把信放到信封中...
邮递信件...
*/
下面我们要通过1个要求来看1下门面模式的优点:
要求:【新建发送之前请先检查信件是不是安全】
//增加了检查信件的Police类
public class Police {
public void checkletter(ILetterProcess letterProcess){
System.out.println(letterProcess + " 信件已被检查过了...");
}
}
//修改ModenPostOffice
public class ModenPostOffice {
//这就是门面对象
private ILetterProcess letterProcess = new LetterProcessImpl();
private Police letterPolice = new Police();
public void sendLetter(String context, String address){
letterProcess.writeContext(context);
letterProcess.fillEnvelope(address);
letterPolice.checkletter(letterProcess);
letterProcess.letterInotoEnvolope();
letterProcess.sendLetter();
}
}
场景类完全1样
//Output
/**
填写信的内容... Hello, It's me, do you know Who I am? I'm your old lover.
填写收信人的姓名和地址...Happy Road No. 666, God Province, Heaven
com.sdkd.LetterProcessImpl@74a14482 信件已被检查过了...
把信放到信封中...
邮递信件...
*/
可以看到这个新的要求对客户是透明的,他甚么都不用管,只是负责告知邮局内容和地址就能够了。
不改变子系统对外暴露的接口 、方法,只改变内部的处理逻辑,其他兄弟模块的调用产生了想要得到结果,这确切是1个非常好的设计。这就是门面模式。
最后的UML图以下,层次模块很明显
门面模式的优点:
1、减少系统的相互依赖
2、提供了灵活性
3、提供了安全性
门面模式的缺点:
门面模式不符合开闭原则,1旦出错风险很大。
门面模式的使用处景:
1、为1个复杂的模块或子系统提供1个供外界访问的接口
2、子系统相对独立,对外界来讲访问只要暗箱操作就能够
3、预防低水平人员带来的风险分散。
上一篇 Codeforces Round #385 (Div. 2) C. Hongcow Builds A Nation 并查集+贪心+组合学、图论、dfs
下一篇 802.11ax前瞻1:协议简介