• 设计模式(十五)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。如果公开的方法过多,那么类的内部的修改会变得困难。如果公开了某个字段,那么其他类可能会读取或是修改这个字段,导致难以修改该类。如果公开了包,那么让外部看到了类,包内的代码的修改就会变得困难。

  • 相关阅读:
    对NETIF_F_GSO的一些理解
    关于ptype_all和pypte_base中的pt_prev的说明[转]
    linux网络收包过程
    linux的pci驱动模型
    linux内核的冷热页分配器
    linux的bootmem内存管理
    GitHub 下载代码命令并且导入到IDEA环境
    配置Log4j(非常具体)
    sudo:有效用户 ID 不是 0,sudo 属于 root 并设置了 setuid 位吗?
    RMP和YUM软件安装
  • 原文地址:https://www.cnblogs.com/BigJunOba/p/8709933.html
Copyright © 2020-2023  润新知