设计模式(十五)Facade模式

  Facade模式可以为相互关联在一起的错综复杂的类整理出高层接口,可以让系统对外只有一个简单的接口,而且还会考虑到系统内部各个类之间的责任关系和依赖关系,按照正常的顺序调用各个类。

  还是先看一下示例程序的类图。

  接下来根据示例程序代码理解一下Facade模式。

 1 package bigjunoba.bjtu.facade;
 2 
 3 import java.io.FileInputStream;
 4 import java.io.IOException;
 5 import java.util.Properties;
 6 
 7 public class Database {
 8 
 9     private Database(){    //防止外部new出Database的实例,所以声明为private
10         }
11     
12     public static Properties getProperties(String dbname) {
13         String filename = dbname + ".txt";
14         Properties properties = new Properties();
15         try {
16             properties.load(new FileInputStream(filename));
17         } catch (IOException e) {
18             System.out.println("找不到文件" + filename);
19         }
20         return properties;
21     }
22     
23 }

  Database类就一个getProperties方法,使用这个方法可以通过传入的dbname来获取对应的Properties实例,properties字段保存的就是读取到的.txt文件。这里要注意的是getProperties是一个静态方法。

 1 package bigjunoba.bjtu.facade;
 2 
 3 import java.io.Writer;
 4 import java.io.IOException;
 5 
 6 public class HtmlWriter {
 7     private Writer writer;
 8     public HtmlWriter(Writer writer) {  // 构造函数
 9         this.writer = writer;
10     }
11     public void title(String title) throws IOException {    // 输出标题
12         writer.write("<html>");
13         writer.write("<head>");
14         writer.write("<title>" + title + "</title>");
15         writer.write("</head>");
16         writer.write("<body>\n");
17         writer.write("<h1>" + title + "</h1>\n");
18     }
19     public void paragraph(String msg) throws IOException {  // 输出段落
20         writer.write("<p>" + msg + "</p>\n");
21     }
22     public void link(String href, String caption) throws IOException {  // 输出超链接
23         paragraph("<a href=\"" + href + "\">" + caption + "</a>");
24     }
25     public void mailto(String mailaddr, String username) throws IOException {   //  输出邮件地址 
26         link("mailto:" + mailaddr, username);
27     }
28     public void close() throws IOException {    // 结束输出HTML
29         writer.write("</body>");
30         writer.write("</html>\n");
31         writer.close();
32     }
33 }

  HtmlWriter类用于编写简单的web页面。在构造HtmlWriter类的实例时赋予其Writer,然后使用该Writer输出HTML。

 1 package bigjunoba.bjtu.facade;
 2 
 3 import java.io.FileWriter;
 4 import java.io.IOException;
 5 import java.util.Properties;
 6 
 7 public class PageMaker {
 8     private PageMaker() {   // 防止外部new出PageMaker的实例,所以声明为private方法
 9     }
10     public static void makeWelcomePage(String mailaddr, String filename) {
11         try {
12             Properties mailprop = Database.getProperties("maildata");
13             String username = mailprop.getProperty(mailaddr);
14             HtmlWriter writer = new HtmlWriter(new FileWriter(filename));
15             writer.title("Welcome to " + username + "'s page!");
16             writer.paragraph("欢迎来到" + username + "的主页。");
17             writer.paragraph("等着你的邮件哦!");
18             writer.mailto(mailaddr, username);
19             writer.close();
20             System.out.println(filename + " is created for " + mailaddr + " (" + username + ")");
21         } catch (IOException e) {
22             e.printStackTrace();
23         }
24     }
25 }

  PageMaker类使用Database类和HtmlWriter类来生成指定用户的Web页面。makeWelcomePage方法会根据指定的邮件地址和文件名生成相应的Web页面。PageMaker类一手包办了调用HTMLWriter类的方法这一工作。对外部,它只提供了makeWelcomePage接口,这就是一个简单窗口。实现过程是,首先调用Database的getProperties方法读取.txt文件,然后生成一个Properties实例,将读取文件的结果保存在mailprop字段中,然后根据输入的邮箱地址通过getProperty方法获取对应的用户名。然后输出一系列Web页面的各个代码部分。

1 package bigjunoba.bjtu.facade;
2 
3 public class Main {
4     public static void main(String[] args) {
5         PageMaker.makeWelcomePage("sjy534948129@sina.com", "welcome.html");
6     }
7 }

  Main类输入文件中保存的邮箱地址和输出文件名来生成一个Web页面。

sjy534948129@sina.com=BigJunOba
17125031@bjtu.edu.cn=Lianjiang

   maildate.txt保存了两条数据。

1 <html><head><title>Welcome to BigJunOba's page!</title></head><body>
2 <h1>Welcome to BigJunOba's page!</h1>
3 <p>欢迎来到BigJunOba的主页。</p>
4 <p>等着你的邮件哦!</p>
5 <p><a href="mailto:sjy534948129@sina.com">BigJunOba</a></p>
6 </body></html>

  welcome.html输出文件。

  Facade模式类图。

  解释一下这些部分:

  Facade:代表构成系统的许多其他部分的“简单窗口”。向外部提供高层接口。示例程序中的PageMaker就是这个。

  其他类:这些类各自完成自己的工作,但是只能是Facade来调用这些其他类工作。示例程序中Database和HtmlWriter类就是这个情况。

  Client:示例程序中的Main只能调用Facade的一个接口,这样就减少了接口的数量。

  

  接口变少的优势:

  程序中如果有很多类和方法,那么在决定到底应该使用哪个类或方法时就会很容易迷茫。类和方法的调用顺序也很容易弄错。然后接口变少可以解决这个问题。

  同时,接口变少还意味着程序与外部的关联关系弱化了,这样更容易使我们的包作为组件被复用。

  还要尤其注意的是,在设计类时,要将哪些方法的可见性设为public。如果公开的方法过多,那么类的内部的修改会变得困难。如果公开了某个字段,那么其他类可能会读取或是修改这个字段,导致难以修改该类。如果公开了包,那么让外部看到了类,包内的代码的修改就会变得困难。

 

posted @ 2018-04-03 17:36  BigJunOba  阅读(234)  评论(0编辑  收藏  举报