`
xyheqhd888
  • 浏览: 409251 次
  • 性别: Icon_minigender_1
  • 来自: 秦皇岛
社区版块
存档分类
最新评论

Facade外观模式

阅读更多

1.Facade模式就是一个功能介于包和完整应用程序之间的类,可提供包或子系统中类的简化功能。Facade模式的目的在于提供一个接口,使子系统更加容易使用

2.外观类、工具类和示例类:

   外观类的方法可能都是静态方法,这种情况下,外观类在UML中被称作工具类示例类就是演示如何使用类或子系统的例子。外观类所能提供的诸多使得之处,示例类也能提供。

3.示例类与外观类的几点区别:

   (1)示例类通常是一个能够独立运行的应用程序,而外观类通常不是;

   (2)示例类通常会包含示例数据,而外观类不会;

   (3)外观类通常是可配置的,而示例类不是;

   (4)外观类旨在提供复用,而示例类不是;

   (5)外观类旨在应用于实际环境中,而示例类不是。

4.javax.swing包中有个JOptionPane类,利用它可以很容易地弹出一个标准对话框。例如,下面的代码会不断地显示一个对话框,直到单击Yes按钮为止。

 
package app.facade;

import javax.swing.*;
import java.awt.Font;

public class ShowOptionPane
{
   public static void main(String[] args)
   {
         Font font = new Font("Dialog",Font.PLAIN,18);
         UIManager.put("Button.font",font);
         UIManager.put("Label.font",font);
         
         int option;
         do
         {
              option = JOptionPane.showConfirmDialog(
                               null,"Had enough?",
                               "A Stubborn Dialog",
                               JOptionPane.YES_NO_OPTION);
         }while(option == JOptionPane.NO_OPION);
   }
}

5. JOptionPane类是一个外观类。该类可配置、可复用,在实际应用中非常易于使用。由于该类通过提供一个简单的接口方便了用户使用JDialog类,因而JOptionPane类符合Facade模式设计意图。有人可能认为外观类是用于简化一个子系统,而单一的JDialog类并不能算是一个子系统。但是正是由于JDialog类具有丰富的特性使得为它创建一个外观类非常有价值。Sun公司在JDK中附带提供了许多示例类。但从它们所在包的名称并没有以java为前缀,我们可以看出这些类并不属于Java类库的一部分。外观类可能属于Java类库的一部分,但示例类不属于Java类库。严格地讲,JOptionPane类并不符合UML关于工具类的定义,因为UML定义一个工具类仅处理静态方法。

6.Java类库中很少有外观类,原因可能源自以下几个方面,这些方面可能截然不同:

  (1)很多人建议Java程序员应该好好研究一下Java类库,但外观类却限制了我们对任何系统的深入使用。它们常常会分散开发人员对Java类库的注意力,并且会引起误会。

  (2)外观类通常介于丰富的包和特定的应用之间。为了创建外观类,开发人员必须事先了解应用程序的类型。但由于Java类库的用户极多,因而这样做几乎是不可能的。

  (3)Java类库提供的外观类极少,这可能是Java类库的一个缺陷。

7.重构为Facade模式

   Facade模式起源于普通的程序开发。当从多个不同类中分离你的代码时,你可能要通过提取访问子系统的类来重构系统

8.下面是利用参数方程画圆的程序代码:

Java代码 复制代码
  1. package app.facade;   
  2.   
  3. import javax.swing.*;   
  4.   
  5. import java.awt.*;   
  6.   
  7. import com.oozinoz.ui.SwingFacade;  //此类下载的源码文件中有   
  8.   
  9. public class ShowCircle extends JPanel {   
  10.     public static void main(String[] args) {   
  11.         ShowCircle sc = new ShowCircle();    
  12.         sc.setPreferredSize(new Dimension(300300));   
  13.         SwingFacade.launch(sc, "Circle");   
  14.     }   
  15.   
  16.     protected void paintComponent(Graphics g) {   
  17.         super.paintComponent(g);   
  18.         int nPoint = 101;   
  19.         double w = getWidth() - 1;   
  20.         double h = getHeight() - 1;   
  21.         double r = Math.min(w, h) / 2.0;   
  22.         int[] x = new int[nPoint];   
  23.         int[] y = new int[nPoint];   
  24.         for (int i = 0; i < nPoint; i++) {   
  25.             double t = ((double) i) / (nPoint - 1);   
  26.             double theta = Math.PI * 2.0 * t;   
  27.             x[i] = (int) (w / 2 + r * Math.cos(theta));   
  28.             y[i] = (int) (h / 2 - r * Math.sin(theta));   
  29.         }   
  30.         g.drawPolyline(x, y, nPoint);   
  31.     }   
  32. }  

 9.假如现在有一个ShowFlight类存在一个问题:它混合了三个目的。其主要目的是作为面板显示焰火弹飞行轨迹。另一个目的是作为一个完整的应用程序,将飞行轨迹面板封装在窗口范围内。第三个目的是计算飞行抛物线。ShowFlight类目前在paintComponent()方法中完成这个计算。

Java代码 复制代码
  1. package app.facade;   
  2.   
  3. /*  
  4.  * Copyright (c) 2001, 2005. Steven J. Metsker.  
  5.  *   
  6.  * Steve Metsker makes no representations or warranties about  
  7.  * the fitness of this software for any particular purpose,   
  8.  * including the implied warranty of merchantability.  
  9.  *  
  10.  * Please use this software as you wish with the sole  
  11.  * restriction that you may not claim that you wrote it.  
  12.  */  
  13.   
  14. import java.awt.Color;   
  15. import java.awt.Dimension;   
  16. import java.awt.Font;   
  17. import java.awt.Graphics;   
  18.   
  19. import javax.swing.BorderFactory;   
  20. import javax.swing.JFrame;   
  21. import javax.swing.JPanel;   
  22. import javax.swing.border.BevelBorder;   
  23. import javax.swing.border.TitledBorder;   
  24.   
  25. public class ShowFlight extends JPanel {   
  26.     /**  
  27.      * Show the flight path of a nonexploding aerial shell. main()方法为用于包含应用程序控件的表单对象增加了间隙。  
  28.      */  
  29.     public static void main(String[] args) {   
  30.         ShowFlight fp = new ShowFlight();   
  31.         fp.setPreferredSize(new Dimension(300200));   
  32.         JPanel fp_titled = createTitledPanel("Flight Path", fp);   
  33.   
  34.         JFrame frame = new JFrame("Flight Path for Shell Duds");   
  35.         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);   
  36.         frame.getContentPane().add(fp_titled);   
  37.   
  38.         frame.pack();   
  39.         frame.setVisible(true);   
  40.     }   
  41.   
  42.     /**  
  43.      * Create a titled border with the given title.  
  44.      */  
  45.     public static TitledBorder createTitledBorder(String title) {   
  46.         TitledBorder tb = BorderFactory.createTitledBorder(BorderFactory   
  47.                 .createBevelBorder(BevelBorder.RAISED), title, TitledBorder.LEFT, TitledBorder.TOP);   
  48.         tb.setTitleColor(Color.black);   
  49.         tb.setTitleFont(getStandardFont());   
  50.         return tb;   
  51.     }   
  52.   
  53.     /**  
  54.      * Create a new panel that wraps a titled border around a given panel.此方法将其提供的控件隐藏在一个斜边框里,以提供小的间隙,使飞行轨迹不会触到边界。  
  55.      */  
  56.     public static JPanel createTitledPanel(String title, JPanel in) {   
  57.         JPanel out = new JPanel();   
  58.         out.add(in);   
  59.         out.setBorder(createTitledBorder(title));   
  60.         return out;   
  61.     }   
  62.   
  63.     /**  
  64.      * @return a standard font for GUI use  
  65.      */  
  66.     public static Font getStandardFont() {   
  67.         return new Font("Dialog", Font.PLAIN, 18);   
  68.     }   
  69.   
  70.     protected void paintComponent(Graphics g) {   
  71.         super.paintComponent(g); // paint the background   
  72.         int nPoint = 101;   
  73.         double w = getWidth() - 1;   
  74.         double h = getHeight() - 1;   
  75.         int[] x = new int[nPoint];   
  76.         int[] y = new int[nPoint];   
  77.         for (int i = 0; i < nPoint; i++) {   
  78.             // t goes 0 to 1   
  79.             double t = ((double) i) / (nPoint - 1);   
  80.             // x goes 0 to w   
  81.             x[i] = (int) (t * w);   
  82.             // y is h at t = 0 and t = 1, and y is 0 at t = .5   
  83.             y[i] = (int) (4 * h * (t - .5) * (t - .5));   
  84.         }   
  85.         g.drawPolyline(x, y, nPoint);   
  86.     }   
  87. }  

 10.可以将上面的ShowFlight类重构为互不关联的类,使得它更具可维护性和可复用性。假设有一个设计评审,并且决定做如下变动:

  (1)引入一个拥有f()方法的Function类,f()方法接受一个double值(时间值),并且返回一个double值(此函数的返回结果)。

  (2)将ShowFlight中绘图代码移植到PlotPanel类中,但是做一些调整,使用Function对象来获取x和y值。定义PlotPanel构造器来接受两个Function实例,以及绘图所需的点的数量。

  (3)从当前的UI工具类中移除createTitledPanel()方法,构造一个像当前的ShowFlight类那样带有标题的面板。

11.将ShowFlight类重构成三个类:Function类,PlotPanel类,UI外观类。在重新设计时,使得ShowFlight2类创建一个获得y值的函数,并且从main()方法开始执行该应用程序。

     注:该图显示了飞行轨迹绘制应用程序被重构为多个类,其中每个类完成一项任务

  

     值得注意的是:createTitledPanel()方法不是静态方法。为了获取标准的用户界面,本设计引用单例NORMAL对象。

请参看UI的相关代码。

     重构之后,Function类定义了参数议程的样子。假设你创建了一个包含Function类及其他类型的com.oozinoz.function包,则Function.java的核心代码可能是:

public abstract double f(double t);

PlotPanel类在重构之后成为具有单独功能的类,用来显示一对参数方程;

      注意PlotPanel类现在是com.oozinoz.ui包的一部分,即和UI类处于同一位置上。ShowFlight类经过重构之后,UI类同样也拥有createTitledPanel()和createTitledBorder()方法。于是UI类便演化为Facade模式,从而使得Java控件的使用更为容易。

      使用这些控件的应用程序可能会是一个很小的类,其功能仅仅为布置这些控件,并且显示它们。请看ShowFlight2类的代码。

      ShowFlight2类提供用来计算哑弹飞行轨迹的YFunction类。main()方法用来布置和显示用户界面。运行这个类所产生的效果和运行最初的ShowFlight类的效果完全一样。但是现在你已经有了一个可复用的、简化Java应用程序中图形用户界面创建过程的Facade模式。

12. 通常,我们应该把子系统的类重构为一个个目的明确的类。这样做可以使代码更加容易维护,但是这样也会让子系统用户不知从何处开始。为了便于子系统用户的使用,我们可以在子系统中顺带提供一些示例类或者外观类。示例类通常是指能够独立运行但不可复用的应用程序,仅用来示范子系统的用法。外观类通常是一个可配置、可复用的类,它为方便用户使用子系统提供了一个更高层次的接口

 

分享到:
评论

相关推荐

    Facade 外观模式(结构型模式)

    C#面向对象设计模式纵横谈\C#面向对象设计模式纵横谈\10.Facade 外观模式(结构型模式).wmv )

    C#面向对象设计模式纵横谈\11 结构型模式Facade外观模式.zip

    在这里与各位分享本人从网络上下载的C#面向对象设计模式纵横谈系列视频,共有25节,除了第一节需要各位贡献一点资源分以作为对本人上传资源的回馈,后面的其他资源均不需要... 这是第11节:结构型模式Facade外观模式

    C#面向对象设计模式纵横谈(11):Facade 外观模式(结构型模式) (Level 300)

    **外观模式(Facade Pattern)**是面向对象设计模式中的一种结构型模式,它提供了一个统一的接口,用于访问子系统中的各个部分。在C#编程中,外观模式可以帮助我们简化复杂的系统接口,使得客户端代码与复杂的内部...

    java 设计模式 Facade外观模式 Simple Factory 简单工厂模式

    外观模式是一种结构型设计模式,它的主要目标是提供一个统一的接口,用来简化对复杂系统的访问。在Java中,当你有一个复杂的子系统,而你希望客户端代码能够以一种更简洁、更易于理解的方式来与之交互时,就可以使用...

    Ajax中使用Facade外观模式的Eclipse版本的Demo

    **Ajax与Facade模式** 在Web开发中,Ajax(Asynchronous JavaScript and XML)技术允许我们创建交互性更强、响应更快的网页。它通过在后台与服务器进行少量数据交换,实现了页面的部分更新,而无需刷新整个页面。...

    设计模式中的facade外观模式在JavaScript开发中的运用_.docx

    外观模式(Facade Pattern)在软件工程中是一种设计模式,它为复杂的系统或子系统提供一个简单的接口,使得客户端可以更容易地使用这些系统或子系统。外观模式的核心思想是通过一个高层次的接口,隐藏子系统的复杂性...

    C++设计模式编程中Facade外观模式的使用实例解析

    Facade外观模式是设计模式中的一种,它的主要目标是为复杂的子系统提供一个简洁的接口,使得客户端(调用者)能更容易地使用这些子系统。在本文中,我们将深入探讨Facade模式的原理、应用场景及其实现方式。 Facade...

    设计模式中的facade外观模式在JavaScript开发中的运用

    外观模式通过引入一个外观角色来简化客户端与子系统之间的交互,为复杂的子系统调用提供一个统一的入口,降低子系统与客户端的耦合,接下来就来看设计模式中的facade外观模式在JavaScript开发中的运用

    设计模式之外观模式(Facade Pattern)

    **外观模式(Facade Pattern)**是一种结构型设计模式,它主要解决的是复杂系统或子系统对外暴露一个简单统一的接口,使得客户端无需关心内部复杂的交互细节。这种模式在实际开发中广泛应用,尤其在大型项目中,它能...

    设计模式之外观模式 facade

    外观模式(Facade Pattern)是设计模式中的一种结构型模式,主要目的是为了解决复杂的系统接口问题,提供一个简单的统一入口,使得客户端可以更方便地使用系统。在Java中,外观模式通常用来隐藏系统的复杂性,对外只...

    23种Python设计模式示例演示源码包.rar

    23种Python设计模式示例演示源码包,比如包括了工厂模式、Bridge桥接模式、Builder构建模式、Facade外观模式、Adapter适配器模式,Composite组合模式、Decorator装饰器模式,FactoryMethod工厂方法模式、Flyweight享...

    外观模式(Facade Pattern)-结构型模式

    设计模式面面观(13):外观模式(Facade Pattern)-结构型模式 http://blog.csdn.net/fanweiwei/archive/2008/04/17/2299641.aspx

    设计模式学习之Facade(外观模式)

    **外观模式(Facade)**是软件工程中一种常用的设计模式,它为复杂的系统或子系统提供了一个统一的入口点,简化了客户端与复杂系统之间的交互。这种模式将客户端与子系统的内部实现细节隔离开来,使得客户端只需要...

    Command和Facade设计模式

    在软件设计模式的世界里,`Command`(命令)和`Facade`(外观)模式是非常重要的两种设计模式。它们分别服务于不同的目的,但都是为了提高代码的可读性、可维护性和灵活性。 `Command`模式是一种行为设计模式,它将...

Global site tag (gtag.js) - Google Analytics