在以前信息不是很发达的时代,人们最快捷的信息往来方式就是通过书信,一般我们写一封书信,一般要经过一下几个步骤:
- 在信纸上写上新的内容
- 在信封上写上收件人的姓名,地址信息
- 将信装进信封,贴上邮票
- 把信送给邮局投递
用类图表示就如下所示:
首先定义一个接口,规范写信的方法:
package facade;
/**
* 写信接口
* @author 77473
*
*/
public interface ILetterProcess {
public void writeContext(String context);//写信的内容
public void writeEnvelope(String address);//写信封地址
public void putLetterIntoEnvelope();//将信放入信封
public void sendLetter();//寄信
}
然后定义一个类实现ILetterProcess的方法
package facade;
/**
* 写信实现类
* @author 77473
*
*/
public class LetterProcessImpl implements ILetterProcess{
public void writeContext(String context) {
// TODO Auto-generated method stub
System.out.println("填写信的内容:"+context);
}
public void writeEnvelope(String address) {
// TODO Auto-generated method stub
System.out.println("填写收件人地址及姓名:"+address);
}
public void putLetterIntoEnvelope() {
// TODO Auto-generated method stub
System.out.println("将信放入信封中...");
}
public void sendLetter() {
// TODO Auto-generated method stub
System.out.println("邮寄信件....");
}
}
最后在场景类中模拟一个写信操作
package facade;
/**
* 场景类
* @author 77473
*
*/
public class Client {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
ILetterProcess letterProcess=new LetterProcessImpl();
letterProcess.writeContext("Hello,It's me,do you know who I am? I'm your old lover. I'd like to..");
letterProcess.writeEnvelope("Happy Road No. 666,God Province,Heaven");
letterProcess.putLetterIntoEnvelope();
letterProcess.sendLetter();
}
}
测试结果:
结果完全正确,但是我们回过头来看看这个过程, 它与高内聚的要求相差甚远, 更不要说迪米特法则、 接口隔离原则了。 你想想, 你要知道这4个步骤, 而且还要知道它们的顺序, 一旦出错, 信就不可能邮寄出去, 这在面向对象的编程中是极度地不适合, 它根本就没有完成一个类所具有的单一职责。还有, 如果信件多了就非常麻烦, 每封信都要这样运转一遍, 非得累死。还好, 现在邮局开发了一个新业务, 你只要把信件的必要信息告诉我, 我给你发, 我来完成这4个过程, 只要把信件交给我就成了, 其他就不要管了。 非常好的方案! 我们来看类图:
其他类不变增加了一个ModernPostOffice类封装写信的整个流程,并且暴露一个sendLetter()方法给外部调用:
package facade;
/**
* 现代邮局类
* @author 77473
*
*/
public class ModernPostOffice {
private ILetterProcess letterProcess=new LetterProcessImpl();//写信流程对象
//写信,封装,投递一体化
public void sendLetter(String context,String address){
//写信的内容
letterProcess.writeContext("Hello,It's me,do you know who I am? I'm your old lover. I'd like to..");
//写信封地址
letterProcess.writeEnvelope("Happy Road No. 666,God Province,Heaven");
//将信放入信封
letterProcess.putLetterIntoEnvelope();
//邮递信件
letterProcess.sendLetter();
}
}
用户不需要知道写信具体要经过哪些步骤,每个步骤的先后顺序,你只要告诉邮局信的内容和收件人地址,邮局就会帮我们把新寄出去了:
package facade;
/**
* 场景类
* @author 77473
*
*/
public class Client {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
ModernPostOffice office=new ModernPostOffice();
office.sendLetter("Hello,It's me,do you know who I am? I'm your old lover. I'd like to..", "Happy Road No. 666,God Province,Heaven");
}
}
这种方式不仅简单,而且扩展性非常好,例如非常时期,我们要对信的内容进行一个检查,此时我们就很容易实现,只需要增加一个Police类:
package facade;
/**
* 检查类,检查新的内容是否健康
* @author 77473
*
*/
public class Police {
//检查信的内容是否反国家,反人类
public void checkLetter(ILetterProcess letter){
System.out.println("已检查通过,信的内容没有反国家,反人类倾向...");
}
}
修改ModernPostOffice.class
package facade;
/**
* 现代邮局类
* @author 77473
*
*/
public class ModernPostOffice {
private ILetterProcess letterProcess=new LetterProcessImpl();
private Police police=new Police();//警察叔叔
//写信,封装,投递一体化
public void sendLetter(String context,String address){
//写信的内容
letterProcess.writeContext("Hello,It's me,do you know who I am? I'm your old lover. I'd like to..");
//写信封地址
letterProcess.writeEnvelope("Happy Road No. 666,God Province,Heaven");
police.checkLetter(letterProcess);//警察叔叔检查信的内容时候健康
//将信放入信封
letterProcess.putLetterIntoEnvelope();
//邮递信件
letterProcess.sendLetter();
}
}
添加一个警察对象,在装信进信封前,添加警察检查的流程。场景类不需要修改,运行如下:
高层模块没有任何改动,但是信已经被检查过了。这正是我们设计所需要的模式,
不改变子系统对外暴露的接口、 方法, 只改变内部的处理逻辑, 其他兄弟模块的调用产生了不同的结果, 确实是一个非常棒的设计。 这就是门面模式。
一、定义
Provide a unified interface to a set of interfaces in a subsystem.Facade defines a higher-levelinterface that makes the subsystem easier to use.( 要求一个子系统的外部与其内部的通信必须通过一个统一的对象进行。 门面模式提供一个高层次的接口, 使得子系统更易于使用。 )
示意图:
二、角色
- Facade门面角色
客户端可以调用这个角色的方法。 此角色知晓子系统的所有功能和责任。 一般情况下,本角色会将所有从客户端发来的请求委派到相应的子系统去, 也就说该角色没有实际的业务逻辑, 只是一个委托类。 - subsystem子系统角色
可以同时有一个或者多个子系统。 每一个子系统都不是一个单独的类, 而是一个类的集合。 子系统并不知道门面的存在。 对于子系统而言, 门面仅仅是另外一个客户端而已。
三、优点
- 减少系统的相互依赖
想想看, 如果我们不使用门面模式, 外界访问直接深入到子系统内部, 相互之间是一种
强耦合关系, 你死我就死, 你活我才能活, 这样的强依赖是系统设计所不能接受的, 门面模
式的出现就很好地解决了该问题, 所有的依赖都是对门面对象的依赖, 与子系统无关。 - 提高了灵活性
依赖减少了, 灵活性自然提高了。 不管子系统内部如何变化, 只要不影响到门面对象,任你自由活动。 - 提高安全性
想让你访问子系统的哪些业务就开通哪些逻辑, 不在门面上开通的方法, 你休想访问到。