门面模式

门面模式

一、什么门面模式?

门面模式(Facade Design Pattern):为子系统提供一组统一的接口,定义一组高层接口让系统更加易用。

二、接口设计存在什么问题?

  • 接口粒度过小时,接口的易用性就会变低,需要调用多个接口才能完成一件事

  • 接口粒度过大时,可复用性就会变低,需要针对不同业务需求实现不同的接口,导致接口无限膨胀

  • 当一个系统的功能越来越强,子系统会越来越多,对子系统的访问也变得越来越复杂

二、门面模式有什么用处?

2.1 设计原理

  • 把粒度小的接口封装统一的门面接口,提高接口的易用性
  • 可以针对不同的业务需求,组装复用接口,形成不同的门面接口
  • 通过为多个复杂的子系统提供一个一致的接口,而使这些子系统更加容易被访问
  • 对外有统一的接口,外部程序无需知道内部子系统的实现,提高了易用性和可维护性

2.2 实际应用场景

  • 在日常编码工作中,我们都在有意无意的大量使用外观模式。比如,高层模块要调度多个模块的类(2个以上的类对象),我们就会创建一个新的类封装它们,并提供精简的接口给高层模块用
  • 各种第三方SDK、开源类库,很大概率都会使用外观模式
  • 移动端通过门面模式可以把很多个请求合并成一个,减少发送的请求数量,提高移动端的加载速度

三、门面模式怎么用?

门面模式不是增加功能接口,实际上只是通过对已有接口进行组合封装,形成一个对外的统一接口。

由门面接口把原始接口组装起来,控制接口的调用顺序,这样外部调用时就不需要自己去实现流程控制了。

3.1 模式结构

门面结构

3.2 示例程序

门面示例程序结构

子系统1(Database):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class Database {

private Database() {
}

public static Properties getProperties(String dbname) {
String filename = "src/com/pattern/facade/" + dbname + ".txt";
Properties prop = new Properties();
try {
prop.load(new FileInputStream(filename));
} catch (IOException e) {
System.out.println("Warning: " + filename + " is not found");
e.printStackTrace();
}
return prop;
}

}

子系统2(HtmlWriter):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public class HtmlWriter {

private Writer writer;

public HtmlWriter(Writer writer) {
this.writer = writer;
}

public void title(String title) throws IOException {
writer.write("<html>");
writer.write("<head>");
writer.write("<title" + title + "</title>");
writer.write("</head>");
writer.write("<body>\n");
writer.write("<h1>" + title + "</h1>\n");
}

public void paragraph(String msg) throws IOException {
writer.write("<p>" + msg + "</p>\n");
}

public void link(String href, String caption) throws IOException {
paragraph("<a href=\"" + href + "\">" + caption + "</a>");
}

public void mailto(String mailAddr, String username) throws IOException {
link("mailto: " + mailAddr, username);
}

public void close() throws IOException {
writer.write("</body>");
writer.write("</html>\n");
writer.close();
}

}

门面接口(PageMaker):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class PageMaker {

private PageMaker(){}

public static void makeWelcomePage(String mailAddr, String filename) {
try {
Properties mailProp = Database.getProperties("maildata");
String username = mailProp.getProperty(mailAddr);
HtmlWriter writer = new HtmlWriter(new FileWriter(filename));
writer.title("Welcome to " + username + "'s page!");
writer.paragraph(username + " 欢迎来到 " + username + " 的主页。");
writer.paragraph("等待你的邮件哦!");
writer.mailto(mailAddr, username);
writer.close();
System.out.println(filename + " is created for " + mailAddr + " (" + username + ")");
} catch (IOException e) {
e.printStackTrace();
}
}

}

四、门面模式的优缺点是什么?

优点:

  • 把粒度小的接口封装统一的门面接口,提高接口的易用性
  • 可以针对不同的业务需求,组装复用接口,形成不同的门面接口

缺点:

  • 违反“开闭原则”,增加新的子系统,可能需要修改门面类的代码
  • 代码的冗余,门面模式实际只是对接口进行组装,并不包含业务功能代码
  • 不可复用性,门面接口一般是针对特定的业务需求组合封装而成,所以复用性不好
作者

jiaduo

发布于

2022-01-15

更新于

2023-04-03

许可协议