《设计模式之禅》学习心得(1)——Facade模式
一、模式定义:
门面模式(Facade Pattern):外部与一个子系统的通信必须通过一个统一的外观对象进行,为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。门面模式又称为外观模式,它是一种对象结构型模式。
简单的来说门面模式就是用来封装复杂的内部的子系统,提供给外部简单的接口而不需要关心内部具体的调用逻辑顺序。
二、场景介绍:
比如你要写一封信给别人,这时候你需要(1)写信的内容;(2)写信封的地址;(3)贴邮票;(4)再把信交给邮局寄出去,总共四个步骤,而且这几个步骤直接还有一定的顺序性,比如第四步肯定是在最后去做的,总不可能信都没写就去寄信了把。那么很明显如果这几个步骤交给每个用户去使用的话是很繁琐的,用户需要记住各个方法调用的顺序以及具体的步骤,譬如我们会这么写:
先定义写信的步骤接口,然后给出实现
package com.pattern.facade;
public interface LetterProcess {
/**
* 写信
* @param content
*/
public abstract void writeLetter(String content);
/**
* 写信封
* @param address
*/
public abstract void fillEnvelope(String address);
/**
* 粘邮票
* @param stamp
*/
public abstract void stickStamp(String stamp);
/**
* 寄信
*/
public abstract void sendLetter();
}
package com.pattern.facade;
public class LetterProcessImp implements LetterProcess {
@Override
public void writeLetter(String content) {
System.out.println("写了信的内容:" + content);
}
@Override
public void fillEnvelope(String address) {
System.out.println("写了信封地址:" + address);
}
@Override
public void stickStamp(String stamp) {
System.out.println("粘了邮票:" + stamp);
}
@Override
public void sendLetter() {
System.out.println("把信寄出啦...");
}
}
然后给出用户调用的逻辑
package com.pattern.facade;
public class Client {
public static void main(String[] args) {
LetterProcess sender = new LetterProcessImp();
sender.writeLetter("信件内容");
sender.fillEnvelope("信的地址");
sender.stickStamp("粘了八毛的邮票");
sender.sendLetter();
}
}
很明显,要是每个用户都得关心这么具体每个步骤,那也太麻烦了,所以这时候我们可以使用门面模式来简化用户的使用过程。
同样的写信接口和实现,我们创建一个facade来帮我们封装这些繁琐的步骤,我们只需要给他写好的信,信的地址和邮票就行了,剩下的让facade帮我们来处理。
package com.pattern.facade;
public class ModernPostOfficeFacade {
private LetterProcess sender = new LetterProcessImp();
private String content;
private String address;
private String stamp;
public ModernPostOffice(String content, String address, String stamp){
this.content = content;
this.address = address;
this.stamp = stamp;
}
public void send(){
sender.writeLetter(content);
sender.fillEnvelope(address);
sender.stickStamp(stamp);
sender.sendLetter();
}
}
这时候我们的用户只要做如下的事就可以了
package com.pattern.facade;
public class HappyClient {
public static void main(String[] args) {
ModernPostOffice office =
new ModernPostOffice("展信上好佳!", "杭州市", "8毛的邮票");
office.send();
}
看到没,瞬间用户就很开心了,只要把所需的内容填写进去就可以啦,再也不用自己一步步去做了。而且有了Facade之后,系统的扩展性也变强了,比如杭州举办G20期间,需要对快递和邮件进行按键,这里假设对个人信件也需要进行检查,看看有没有传递一些违反国家安全的内容,如果是之前的形式,那么需要对每一个用户都加上检查的步骤,OMG,我估计用户都快要疯了。但在Facade模式下,一切都变得很简单。
package com.pattern.facade;
public class ModernPostOffice {
private LetterProcess sender = new LetterProcessImp();
private HZPoliceCheckImp police = new HZPoliceCheckImp();
private String content;
private String address;
private String stamp;
public ModernPostOffice(String content, String address, String stamp){
this.content = content;
this.address = address;
this.stamp = stamp;
}
public void send(){
sender.writeLetter(content);
sender.fillEnvelope(address);
sender.stickStamp(stamp);
//只需要在这里加一步检查就OK了,整个寄信过程对用户是透明的
police.checkLetter();
sender.sendLetter();
}
}
看到没,对用户来说,他不关心寄信的具体过程,他只关心你最后能把信帮我寄到就OK,因此有了Facade之后,一切变得非常完美!
ps:说实话,我在学习过程中一开始觉得门面模式跟代理模式有点相像,后面查了些资料,我觉得代理模式更多是对一个对象的代理,用户无法直接访问到对象,而需要代理对象来进行,它是被代理对象的一个代表,类似于一个经纪人,你要跟原本对象打交道都得先通过我。而通常外观模式更多是提供对子系统各元件功能的简化的共同层次的调用接口,定义一组新的接口,方便用户更方便使用底下现有复杂的子系统提供的功能。