• 设计模式(十五)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>
    ");
    17         writer.write("<h1>" + title + "</h1>
    ");
    18     }
    19     public void paragraph(String msg) throws IOException {  // 输出段落
    20         writer.write("<p>" + msg + "</p>
    ");
    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>
    ");
    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。如果公开的方法过多,那么类的内部的修改会变得困难。如果公开了某个字段,那么其他类可能会读取或是修改这个字段,导致难以修改该类。如果公开了包,那么让外部看到了类,包内的代码的修改就会变得困难。

  • 相关阅读:
    修复 Visual Studio Error “No exports were found that match the constraint”
    RabbitMQ Config
    Entity Framework Extended Library
    Navisworks API 简单二次开发 (自定义工具条)
    NavisWorks Api 简单使用与Gantt
    SQL SERVER 竖表变成横表
    SQL SERVER 多数据导入
    Devexpress GridControl.Export
    mongo DB for C#
    Devexress XPO xpPageSelector 使用
  • 原文地址:https://www.cnblogs.com/BigJunOba/p/8709933.html
Copyright © 2020-2023  润新知