以下只是个人的一些理解,可能有一些错误或者误解,不建议根据本文来了解设计模式,如果要学习设计模式的话,还是建议找专业书籍资料学习。

01门面模式(外观模式)

引出

如果一个项目中有多个子系统,客户需要使用多个子系统中的某些功能,如果不使用门面模式的话就可能造成这种情况,用户与多个子系统之间打交道,造成了系统与用户之间的耦合过高。

图一

 

 

 

 

 

 

 

 图二

但是如果使用了门面模式这种局面就会得以改善,使得用户和各个子系统之间的耦合度降低

 

以下是代码实现。

代码(不使用门面模式)

A子系统

 1 package designMode.facadeMode;
 2 
 3 /**
 4  * @author littstone
 5  *  A子系统
 6  * @date 2022/7/28 - 17:14
 7  */
 8 public class A {
 9 
10     public void a() {
11         System.out.println("执行了A类中的a方法");
12     }
13 
14     public void b() {
15         System.out.println("执行了A类中的b方法");
16     }
17 }

 B子系统

 1 package designMode.facadeMode;
 2 
 3 /**
 4  * @author littstone
 5  * B子系统
 6  * @date 2022/7/28 - 17:15
 7  */
 8 public class B {
 9     public void a() {
10         System.out.println("执行了B类里的a方法");
11     }
12 
13     public void b() {
14         System.out.println("执行了B类里的b方法");
15     }
16 }

C子系统

 1 package designMode.facadeMode;
 2 
 3 /**
 4  * @author littstone
 5  *  C子系统
 6  * @date 2022/7/28 - 17:16
 7  */
 8 public class C {
 9     public void a() {
10         System.out.println("执行了C类里的a方法");
11     }
12 
13     public void b() {
14         System.out.println("执行了C类里的b方法");
15     }
16 }

用户

 1 package designMode.facadeMode;
 2 
 3 /**
 4  * @author littstone
 5  * @date 2022/7/28 - 17:36
 6  */
 7 public class User {
 8     /**
 9      * 看作是用户
10      * @param args
11      */
12     public static void main(String[] args) {
13         new A().a();
14         new B().a();
15         new C().a();
16     }
17     /**
18      * 输出结果
19      * 执行了A类中的a方法
20      * 执行了B类里的a方法
21      * 执行了C类里的a方法
22      */
23 }

结论:可以看到虽然成功调用了子系统中的方法,但是是通过直接获取子系统中方法所在的类的对象直接调用的,因此就会产生图一的情况。

代码(使用门面模式)

创建门面类DoorFace

 1 package designMode.facadeMode;
 2 
 3 /**
 4  * @author littstone
 5  * @date 2022/7/28 - 17:18
 6  */
 7 public class DoorFace {
 8     public void a(){
 9         new A().a();
10         new A().b();
11         new B().a();
12         new B().b();
13         new C().a();
14         new C().b();
15     }
16 }

修改User类

 1 package designMode.facadeMode;
 2 
 3 /**
 4  * @author littstone
 5  * @date 2022/7/28 - 17:36
 6  */
 7 public class User {
 8     /**
 9      * 当前用户
10      */
11     public void a() {
12         new DoorFace().a();
13     }
14 }
15 
16 package designMode.facadeMode;
17 
18 /**
19  * @author littstone
20  * @date 2022/7/28 - 17:36
21  */
22 public class User {
23     /**
24      * 当前用户
25      */
26     public static void main(String[] args) {
27         new DoorFace().a();
28     }
29     /**
30      * 执行了A类中的a方法
31      * 执行了A类中的b方法
32      * 执行了B类里的a方法
33      * 执行了B类里的b方法
34      * 执行了C类里的a方法
35      * 执行了C类里的b方法
36      */
37 }

结论:可以看到用户并没有通过直接调用子系统中的方法,而是通过了一个媒介——门面类就完成了因要实现的功能。至于与子系统打交道就交给了门面类来做了。因此也实现了图二的效果。

优点其一(选择性暴漏)

问题:如果还是未使用门面类用户直接调用子系统中的方法,那么用户就可以看到当前子系统中的所有方法(public),但是有些方法是子系统之间来交流的,这些方法不能够被用户所看到。要实现用户只能看到当前类中的一部分这个要求,可以借助门面模式来实现。

实现

修改FaceDoor类

 1 package designMode.facadeMode;
 2 
 3 /**
 4  * @author littstone
 5  * @date 2022/7/28 - 17:18
 6  */
 7 public class DoorFace {
 8     /**
 9      * 选择性的调用各个子系统中的方法,如果某些方法不希望用户看到
10      * 就可以不在门面类里面调用这个方法。
11      */
12     public void a(){
13         new A().a();
14         new B().a();
15         new C().a();
16     }
17 }

User类

 1 package designMode.facadeMode;
 2 
 3 /**
 4  * @author littstone
 5  * @date 2022/7/28 - 17:36
 6  */
 7 public class User {
 8     /**
 9      * 当前用户
10      */
11     public static void main(String[] args) {
12         new DoorFace().a();
13     }
14     /**
15      * 执行了A类中的a方法
16      * 执行了B类里的a方法
17      * 执行了C类里的a方法
18      */
19 }

结论:可以看到即使User类没有丝毫改变,但是调用的结果却发生了变化,这样就可以实现选择性暴漏子系统中的方法,提高了一些安全性也不至于调出太多的方法导致用户产生困惑。

使用场景

1:子系统的功能逐渐增多,需要提供一个接口简化方法的调用。

2:构建多层系统设计,可以使用门面模式来作为每层的入口。

---end---