Java资源网

| JAVA基础 | 环境配置 | JDBC | 线程技术 | Socket编程 | JavaMail | JAVA与XML | 设计模式 | 技术新闻 | Java认证 | 程序人生 软件下载
| JSP&Servlet | Spring | Struts | Hibernate | JBuilder | Eclipse | WebService | EJB技术 | J2ME开发 | 应用服务器 | JXTA | Ajax
Articles search文章搜索
   关键字:
   类 别:
       
New download 最新下载
· [组件]HTML Parser 1.5
· [教程]WebSphere Studio应用教程
· [组件]JDom 1.0
· [工具]Junit3.8.1
· [教程]EJB编程及J2EE系统架构和设计
· [教程]EJB教程
· [教程]J2EE Tutorial中文版
· [教程]Java编程思想2(英文)
· [教程]java编程思想(完整版)
· [教程]Java网络编程
New articles 最新文章
· 设计移动 Web 服务
· 解析XML的时候完全忽略DTD
· 理解XML Schema XML Schema 初步
· 标签库的深入研究
· 提升JSP应用程序的七大绝招
· 如何使用JDOM对XML文件进行操作
· 处理XML字符串中特殊字符
· 利用Digester把XML转换成为Java对象
· 使用WebService 和RMI远程协作
· 使用Axis开发Web Service程序
Articles top 热门文章
· Eclipse基础--plugin插件安装(6644)
· eclipse+tomcat+lomboz的安装配置说明(4774)
· Java程序员就业前景(4584)
· Windows下JAVA环境变量的设置祥解(3788)
· Tomcat下JSP、Servlet和JavaBean环境的配置(3716)
· 使用links方式安装Eclipse插件(3698)
· 一个老程序员的心理话(3533)
· linux下jdk的安装与配置(3459)
· 初学者入门:Structs中基本配置入门(3334)
· Eclipse 运行命令行参数大全(3084)
您的位置:首页>>设计模式>>外观模式(Faccedil;adenbsp;pattern)
外观模式(Faccedil;adenbsp;pattern)
2007-04-13   来源:www.javaresearch.org  作者:未知

本文是翻译《Software Architecture Design Patterns in Java》一书,我将陆续为大家翻译其他章节,希望大家支持指正!

第22章:外观模式(Façade pattern)


    

描述:


    外观模式(Façade pattern)涉及到子系统的一些类。所谓子系统,是为提供一系列相关的特征(功能)而紧密关联的一组类。例如,一个Account类、Address类和CreditCard类相互关联,成为子系统的一部分,提供在线客户的特征。
    在真实的应用系统中,一个子系统可能由很多类组成。子系统的客户为了它们的需要,需要和子系统中的一些类进行交互。客户和子系统的类进行直接的交互会导致客户端对象和子系统(Figure 22.1)之间高度耦合。任何的类似于对子系统中类的接口的修改,会对依赖于它的所有的客户类造成影响。
  
Figure 22.1: Client Interaction with Subsystem Classes before Applying the Façade Pattern 
外观模式(Façade pattern)很适用于在上述情况。外观模式(Façade pattern)为子系统提供了一个更高层次、更简单的接口,从而降低了子系统的复杂度和依赖。这使得子系统更易于使用和管理。
外观是一个能为子系统和客户提供简单接口的类。当正确的应用外观,客户不再直接和子系统中的类交互,而是与外观交互。外观承担与子系统中类交互的责任。实际上,外观是子系统与客户的接口,这样外观模式降低了子系统和客户的耦合度(Figure 22.2).  
 
Figure 22.2: Client Interaction with Subsystem Classes after Applying the Façade Pattern 
从Figure 22.2中我们可以看到:外观对象隔离了客户和子系统对象,从而降低了耦合度。当子系统中的类进行改变时,客户端不会像以前一样受到影响。
尽管客户使用由外观提供的简单接口,但是当需要的时候,客户端还是可以视外观不存在,直接访问子系统中的底层次的接口。这种情况下,它们之间的依赖/耦合度和原来一样。

例子:


让我们建立一个应用:
(1)    接受客户的详细资料(账户、地址和信用卡信息)
(2)    验证输入的信息
(3)    保存输入的信息到相应的文件中。
这个应用有三个类:Account、Address和CreditCard。每一个类都有自己的验证和保存数据的方法。
Listing 22.1: AccountClass 
  1. public class Account { 
  2.   String firstName; 
  3.   String lastName; 
  4.   final String ACCOUNT_DATA_FILE = "AccountData.txt"
  5.   public Account(String fname, String lname) { 
  6.     firstName = fname; 
  7.     lastName = lname; 
  8.   } 
  9.   public boolean isValid() { 
  10.     /* 
  11.      Let's go with simpler validation 
  12.      here to keep the example simpler. 
  13.     */ 
  14.         … 
  15.         … 
  16.   } 
  17.   public boolean save() { 
  18.     FileUtil futil = new FileUtil(); 
  19.     String dataLine = getLastName() + ”," + getFirstName(); 
  20.     return futil.writeToFile(ACCOUNT_DATA_FILE, dataLine, 
  21.     truetrue); 
  22.   } 
  23.   public String getFirstName() { 
  24.     return firstName; 
  25.   } 
  26.   public String getLastName() { 
  27.     return lastName; 
  28.   } 

Listing 22.2: Address Class 
  1. public class Address { 
  2.   String address; 
  3.   String city; 
  4.   String state; 
  5.   final String ADDRESS_DATA_FILE = "Address.txt"
  6.   public Address(String add, String cty, String st) { 
  7.     address = add; 
  8.     city = cty; 
  9.     state = st; 
  10.   } 
  11.   public boolean isValid() { 
  12.      /* 
  13.        The address validation algorithm 
  14.        could be complex in real-world 
  15.        applications. 
  16.        Let's go with simpler validation 
  17.        here to keep the example simpler. 
  18.       */ 
  19.     if (getState().trim().length() < 2) 
  20.        return false
  21.     return true
  22.   } 
  23.   public boolean save() { 
  24.     FileUtil futil = new FileUtil(); 
  25.     String dataLine = getAddress() + ”," + getCity() + ”," + 
  26.                       getState(); 
  27.     return futil.writeToFile(ADDRESS_DATA_FILE, dataLine, 
  28.            truetrue); 
  29.   } 
  30.   public String getAddress() { 
  31.     return address; 
  32.   } 
  33.   public String getCity() { 
  34.     return city; 
  35.   } 
  36.   public String getState() { 
  37.     return state; 
  38.   } 

Listing 22.3: CreditCard Class 
  1. public class CreditCard { 
  2.   String cardType; 
  3.   String cardNumber; 
  4.   String cardExpDate; 
  5.   final String CC_DATA_FILE = "CC.txt"
  6.   public CreditCard(String ccType, String ccNumber, 
  7.                     String ccExpDate) { 
  8.     cardType = ccType; 
  9.     cardNumber = ccNumber; 
  10.     cardExpDate = ccExpDate; 
  11.   } 
  12.   public boolean isValid() { 
  13.     /* 
  14.      Let's go with simpler validation 
  15.      here to keep the example simpler. 
  16.     */ 
  17.     if (getCardType().equals(AccountManager.VISA)) { 
  18.       return (getCardNumber().trim().length() == 16); 
  19.     } 
  20.     if (getCardType().equals(AccountManager.DISCOVER)) { 
  21.       return (getCardNumber().trim().length() == 15); 
  22.     } 
  23.     if (getCardType().equals(AccountManager.MASTER)) { 
  24.       return (getCardNumber().trim().length() == 16); 
  25.     } 
  26.       return false
  27.   } 
  28.   public boolean save() { 
  29.     FileUtil futil = new FileUtil(); 
  30.     String dataLine = 
  31.       getCardType() + ,”" + getCardNumber() + ”," + 
  32.       getCardExpDate(); 
  33.     return futil.writeToFile(CC_DATA_FILE, dataLine, true
  34.            true); 
  35.   } 
  36.   public String getCardType() { 
  37.     return cardType; 
  38.   } 
  39.   public String getCardNumber() { 
  40.     return cardNumber; 
  41.   } 
  42.   public String getCardExpDate() { 
  43.     return cardExpDate; 
  44.   } 

  
Figure 22.3: Subsystem Classes to Provide the Necessary Functionality to Validate and Save the Customer Data 
让我们建立一个客户AccountManager,它提供用户输入数据的用户界面。
Listing 22.4: Client AccountManager Class 
  1. public class AccountManager extends JFrame { 
  2.   public static final String newline = "\n"
  3.   public static final String VALIDATE_SAVE = "Validate & Save"
  4.            … 
  5.            … 
  6.   public AccountManager() { 
  7.     super(" Facade Pattern - Example "); 
  8.     cmbCardType = new JComboBox(); 
  9.     cmbCardType.addItem(AccountManager.VISA); 
  10.     cmbCardType.addItem(AccountManager.MASTER); 
  11.     cmbCardType.addItem(AccountManager.DISCOVER); 
  12.            … 
  13.            … 
  14.     //Create buttons 
  15.     JButton validateSaveButton = 
  16.       new JButton(AccountManager.VALIDATE_SAVE); 
  17.            … 
  18.            … 
  19.   } 
  20.   public String getFirstName()  { 
  21.     return txtFirstName.getText(); 
  22.   } 
  23.            … 
  24.            … 
  25. }//End of class AccountManager 

当客户AccountManage运行的时候,展示的用户接口如下:
 
 
Figure 22.4: User Interface to Enter the Customer Data 
为了验证和保存输入的数据,客户AccountManager需要:
(1)    建立Account、Address和CreditCard对象。
(2)    用这些对象验证输入的数据
(3)    用这些对象保存输入的数据。
下面是对象间的交互顺序图:
 
 
Figure 22.5: How a Client Would Normally Interact (Directly) with Subsystem Classes to Validate and Save the Customer Data 
在这个例子中应用外观模式是一个很好的设计,它可以降低客户和子系统组件(Address、Account和CreditCard)之间的耦合度。应用外观模式,让我们定义一个外观类CustomerFacade (Figure 22.6 and Listing 22.5)。它为由客户数据处理类(Address、Account和CreditCard)所组成的子系统提供一个高层次的、简单的接口。
CustomerFacade 
address:String 
city:String 
state:String 
cardType:String 
cardNumber:String 
cardExpDate:String 
fname:String 
lname:String 
setAddress(inAddress:String) 
setCity(inCity:String) 
setState(inState:String) 
setCardType(inCardType:String) 
setCardNumber(inCardNumber:String) 
setCardExpDate(inCardExpDate:String) 
setFName(inFName:String) 
setLName(inLName:String) 
saveCustomerData() 
 
Figure 22.6: Façade Class to Be Used by the Client in the Revised Design 
Listing 22.5: CustomerFacade Class 
  1. public class CustomerFacade { 
  2.   private String address; 
  3.   private String city; 
  4.   private String state; 
  5.   private String cardType; 
  6.   private String cardNumber; 
  7.   private String cardExpDate; 
  8.   private String fname; 
  9.   private String lname; 
  10.   public void setAddress(String inAddress) { 
  11.     address = inAddress; 
  12.   } 
  13.   public void setCity(String inCity) { 
  14.     city = inCity; 
  15.   } 
  16.   public void setState(String inState) { 
  17.     state = inState; 
  18.   } 
  19.   public void setFName(String inFName) { 
  20.     fname = inFName; 
  21.   } 
  22.   public void setLName(String inLName) { 
  23.     lname = inLName; 
  24.   } 
  25.   public void setCardType(String inCardType) { 
  26.     cardType = inCardType; 
  27.   } 
  28.   public void setCardNumber(String inCardNumber) { 
  29.     cardNumber = inCardNumber; 
  30.   } 
  31.   public void setCardExpDate(String inCardExpDate) { 
  32.     cardExpDate = inCardExpDate; 
  33.   } 
  34.   public boolean saveCustomerData() { 
  35.     Address objAddress; 
  36.     Account objAccount; 
  37.     CreditCard objCreditCard; 
  38.     /* 
  39.      client is transparent from the following 
  40.      set of subsystem related operations. 
  41.     */ 
  42.     boolean validData = true
  43.     String errorMessage = ""
  44.     objAccount = new Account(fname, lname); 
  45.     if (objAccount.isValid() == false) { 
  46.       validData = false
  47.       errorMessage = "Invalid FirstName/LastName"
  48.     } 
  49.     objAddress = new Address(address, city, state); 
  50.     if (objAddress.isValid() == false) { 
  51.       validData = false
  52.       errorMessage = "Invalid Address/City/State"
  53.     } 
  54.     objCreditCard = new CreditCard(cardType, cardNumber, 
  55.                     cardExpDate); 
  56.     if (objCreditCard.isValid() == false) { 
  57.       validData = false
  58.       errorMessage = "Invalid CreditCard Info"
  59.     } 
  60.     if (!validData) { 
  61.       System.out.println(errorMessage); 
  62.       return false
  63.     } 
  64.     if (objAddress.save() && objAccount.save() && 
  65.         objCreditCard.save()) { 
  66.       return true
  67.     }  else { 
  68.       return false
  69.     } 
  70.   } 

    CustomerFacade类以saveCustomData方法的形式提供了业务层次上的服务。客户AccountManager不是直接和子系统的每一个组件交互,而是使用了由CustomFacade对象提供的验证和保存客户数据的更高层次、更简单的接口(Figure 22.7).
  
Figure 22.7: Class Association with the Façade Class in Place 。
    在新的设计中,为了验证和保存客户数据,客户需要:
(1)    建立或获得外观对象CustomFacade的一个实例。
(2)    传递数据给CustomFacade实例进行验证和保存。
(3)    调用CustomFacade实例上的saveCustomData方法。
CustomFacade处理创建子系统中必要的对象并且调用这些对象上相应的验证、保存客户数据的方法这些细节问题。客户不再需要直接访问任何的子系统中的对象。
Figure 22.8展示了新的设计的消息流图:
 
 
Figure 22.8: In the Revised Design, Clients Interact with the Façade Instance to Interface with the Subsystem 

重要提示:


下面是应用外观模式的注意事项:
(1)    在设计外观时,不需要增加额外的功能。
(2)    不要从外观方法中返回子系统中的组件给客户。例如:有一个下面的方法:
CreditCard getCreditCard() 
会报漏子系统的细节给客户。应用就不能从应用外观模式中取得最大的好处。
(3)应用外观的目的是提供一个高层次的接口。因此,外观方法最适合提供特定的高层次的业务服务,而不是进行底层次的单独的业务执行。
附件为本文的代码和原文!请大家指正!附件:26.rar(5K) 附件:Chapter_22.doc(273K) 

  --相关文章--
· 面向对象编程,我的思想 (2007-04-13)
· 面向对象的思维方式 (2007-04-13)
· 通过Javanbsp;Swing看透MVC设计模式 (2007-04-13)
· 适配器模式(Adapternbsp;Pattern) (2007-04-13)
· 追MM与Java的23种设计模式 (2007-04-13)
· 责任链模式(Chainnbsp;ofnbsp;Responsibility) (2007-04-13)

版权所有©2005-2006 JAVA资源网 渝ICP备05007591号 虚拟主机 | 关于我们 | 联系方式 | 广告业务 | 网站地图 | 友情链接