门面模式(Facade Pattern)又叫作外观模式,提供了一个统一的接口,用来访问子系统中的一群接口。其主要特征是定义了一个高层接口,让子系统更容易使用,属于结构型设计模式。
其实,在日常编码工作中,我们都在有意无意地大量使用门面模式。但凡只要高层模块需要调度多个子系统(2个以上类对象),我们都会自觉地创建一个新类封装这些子系统,提供精简的接口,让高层模块可以更加容易地间接调用这些子系统的功能。
来个简单的demo:
我u有以下三个service:
- public class ServiceA {
- public void doA(){
- System.out.println("do ServiceA");
- }
- }
- public class ServiceB {
- public void doB(){
- System.out.println("do ServiceB");
- }
- }
-
- public class ServiceC {
- public void doC(){
- System.out.println("do ServiceC");
- }
- }
在没有引入门面模式的时候,我们是这么调用的:
- public class Client {
- public static void main(String[] args) {
- ServiceA serviceA = new ServiceA();
- ServiceB serviceB = new ServiceB();
- ServiceC serviceC = new ServiceC();
-
- serviceA.doA();
- serviceB.doB();
- serviceC.doC();
- }
- }
没啥毛病啊,结合到spingmvc开发,这些service交给spring管理,根本不用自己new了,直接注入到controller就可以,但是如果10个地方都用了这三个service呢?这10个controller里都注入一下?这时候考虑优化——我可以新建一个service,持有这个三个service不就ok了吗:
- public class ServiceFacade {
- //是不是很像我们controller里注入各种service?
- private ServiceA serviceA = new ServiceA();
- private ServiceB serviceB = new ServiceB();
- private ServiceC serviceC = new ServiceC();
-
- public void doA() {
- serviceA.doA();
- }
-
- public void doB() {
- serviceB.doB();
- }
-
- public void doC() {
- serviceC.doC();
- }
- }
客户端就变成了
- public class Client {
- public static void main(String[] args) {
- //轻轻松松的搞定,只需要创建门面这个对象即可
- ServiceFacade serviceFacade= new ServiceFacade ();
- serviceFacade.doA();
- serviceFacade.doB();
- serviceFacade.doC();
- }
- }
由上图可以看到,门面模式主要包含2个角色。
优点
● 减少系统的相互依赖 想想看,如果我们不使用门面模式,外界访问直接深入到子系统内部,相互之间是一种强耦合关系,你死我就死,你活我才能活,这样的强依赖是系统设计所不能接受的,门面模式的出现就很好地解决了该问题,所有的依赖都是对门面对象的依赖,与子系统无关。
● 提高了灵活性 依赖减少了,灵活性自然提高了。不管子系统内部如何变化,只要不影响到门面对象,任你自由活动。
● 提高安全性 想让你访问子系统的哪些业务就开通哪些逻辑,不在门面上开通的方法,你休想访问到 。
缺点
当增加子系统和扩展子系统行为时,可能容易带来未知风险。
不符合开闭原则。
某些情况下,可能违背单一职责原则。