门面模式
一、什么门面模式?
门面模式(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(); } }
}
|
四、门面模式的优缺点是什么?
优点:
- 把粒度小的接口封装统一的门面接口,提高接口的易用性
- 可以针对不同的业务需求,组装复用接口,形成不同的门面接口
缺点:
- 违反“开闭原则”,增加新的子系统,可能需要修改门面类的代码
- 代码的冗余,门面模式实际只是对接口进行组装,并不包含业务功能代码
- 不可复用性,门面接口一般是针对特定的业务需求组合封装而成,所以复用性不好