每日一得

          不求多得,只求一得 about java,hibernate,spring,design,database,Ror,ruby,快速開發
          最近關心的內容:SSH,seam,flex,敏捷,TDD
          本站的官方站點是:顛覆軟件

            BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
            220 隨筆 :: 9 文章 :: 421 評論 :: 0 Trackbacks
          外觀模式(Facade pattern)涉及到子系統的一些類。所謂子系統,是為提供一系列相關的特征(功能)而緊密關聯的一組類。例如,一個Account類、Address類和CreditCard類相互關聯,成為子系統的一部分,提供在線客戶的特征。

             在真實的應用系統中,一個子系統可能由很多類組成。子系統的客戶為了它們的需要,需要和子系統中的一些類進行交互。客戶和子系統的類進行直接的交互會導 致客戶端對象和子系統(Figure1)之間高度耦合。任何的類似于對子系統中類的接口的修改,會對依賴于它的所有的客戶類造成影響。

          ??
          Figure1: Client Interaction with Subsystem Classes before Applying the Facade Pattern

            外觀模式(Facade pattern)很適用于在上述情況。外觀模式(Facade pattern)為子系統提供了一個更高層次、更簡單的接口,從而降低了子系統的復雜度和依賴。這使得子系統更易于使用和管理。

            外觀是一個能為子系統和客戶提供簡單接口的類。當正確的應用外觀,客戶不再直接和子系統中的類交互,而是與外觀交互。外觀承擔與子系統中類交互的責任。實際上,外觀是子系統與客戶的接口,這樣外觀模式降低了子系統和客戶的耦合度(Figure2).

          ??
          Figure2: Client Interaction with Subsystem Classes after Applying the Facade Pattern

            從Figure2中我們可以看到:外觀對象隔離了客戶和子系統對象,從而降低了耦合度。當子系統中的類進行改變時,客戶端不會像以前一樣受到影響。

            盡管客戶使用由外觀提供的簡單接口,但是當需要的時候,客戶端還是可以視外觀不存在,直接訪問子系統中的底層次的接口。這種情況下,它們之間的依賴/耦合度和原來一樣。

            例子:

            讓我們建立一個應用:

            (1) 接受客戶的詳細資料(賬戶、地址和信用卡信息)

            (2) 驗證輸入的信息

            (3) 保存輸入的信息到相應的文件中。

            這個應用有三個類:Account、Address和CreditCard。每一個類都有自己的驗證和保存數據的方法。

            Listing1: AccountClass

          public class Account {
           String firstName;
           String lastName;
           final String ACCOUNT_DATA_FILE = "AccountData.txt";
           public Account(String fname, String lname) {
            firstName = fname;
            lastName = lname;
           }
           public boolean isValid() {
            /*
            Let's go with simpler validation
            here to keep the example simpler.
            */
            …
            …
           }
           public boolean save() {
            FileUtil futil = new FileUtil();
            String dataLine = getLastName() + ”," + getFirstName();
            return futil.writeToFile(ACCOUNT_DATA_FILE, dataLine,true, true);
           }
           public String getFirstName() {
            return firstName;
           }
           public String getLastName() {
            return lastName;
           }
          }

            Listing2: Address Class

          public class Address {
           String address;
           String city;
           String state;
           final String ADDRESS_DATA_FILE = "Address.txt";
           public Address(String add, String cty, String st) {
            address = add;
            city = cty;
            state = st;
           }
           public boolean isValid() {
            /*
            The address validation algorithm
            could be complex in real-world
            applications.
            Let's go with simpler validation
            here to keep the example simpler.
            */
            if (getState().trim().length() < 2)
             return false;
            return true;
           }
           public boolean save() {
            FileUtil futil = new FileUtil();
            String dataLine = getAddress() + ”," + getCity() + ”," + getState();
            return futil.writeToFile(ADDRESS_DATA_FILE, dataLine,true, true);
           }
           public String getAddress() {
            return address;
           }
           public String getCity() {
            return city;
           }
           public String getState() {
            return state;
           }
          }

            Listing3: CreditCard Class

          public class CreditCard {
           String cardType;
           String cardNumber;
           String cardExpDate;
           final String CC_DATA_FILE = "CC.txt";
           public CreditCard(String ccType, String ccNumber,
           String ccExpDate) {
            cardType = ccType;
            cardNumber = ccNumber;
            cardExpDate = ccExpDate;
           }
           public boolean isValid() {
            /*
            Let's go with simpler validation
            here to keep the example simpler.
            */
            if (getCardType().equals(AccountManager.VISA)) {
             return (getCardNumber().trim().length() == 16);
            }
            if (getCardType().equals(AccountManager.DISCOVER)) {
             return (getCardNumber().trim().length() == 15);
            }
            if (getCardType().equals(AccountManager.MASTER)) {
             return (getCardNumber().trim().length() == 16);
            }
            return false;
           }
           public boolean save() {
            FileUtil futil = new FileUtil();
            String dataLine = getCardType() + ,”" + getCardNumber() + ”," + getCardExpDate();
            return futil.writeToFile(CC_DATA_FILE, dataLine, true, true);
           }
           public String getCardType() {
            return cardType;
           }
           public String getCardNumber() {
            return cardNumber;
           }
           public String getCardExpDate() {
            return cardExpDate;
           }
          }

          ??
          Figure3: Subsystem Classes to Provide the Necessary Functionality to Validate and Save the Customer Data



          讓我們建立一個客戶AccountManager,它提供用戶輸入數據的用戶界面。

            Listing4: Client AccountManager Class

          public class AccountManager extends JFrame {
           public static final String newline = "\n";
           public static final String VALIDATE_SAVE = "Validate & Save";
           …
           …
           public AccountManager() {
            super(" Facade Pattern - Example ");
            cmbCardType = new JComboBox();
            cmbCardType.addItem(AccountManager.VISA);
            cmbCardType.addItem(AccountManager.MASTER);
            cmbCardType.addItem(AccountManager.DISCOVER);
            …
            …
            //Create buttons
            JButton validateSaveButton = new JButton(AccountManager.VALIDATE_SAVE);
            …
            …
           }
           public String getFirstName() {
            return txtFirstName.getText();
           }
           …
           …
          }//End of class AccountManager

            當客戶AccountManage運行的時候,展示的用戶接口如下:

          ??
          Figure4: User Interface to Enter the Customer Data

            為了驗證和保存輸入的數據,客戶AccountManager需要:

            (1) 建立Account、Address和CreditCard對象。

            (2) 用這些對象驗證輸入的數據

            (3) 用這些對象保存輸入的數據。

            下面是對象間的交互順序圖:

          ?
          Figure5: How a Client Would Normally Interact (Directly) with Subsystem Classes to Validate and Save the Customer Data

             在這個例子中應用外觀模式是一個很好的設計,它可以降低客戶和子系統組件(Address、Account和CreditCard)之間的耦合度。應用 外觀模式,讓我們定義一個外觀類CustomerFacade (Figure6 and Listing5)。它為由客戶數據處理類(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()

          ??
          Figure6: Facade Class to Be Used by the Client in the Revised Design

            Listing5: CustomerFacade Class

          public class CustomerFacade {
           private String address;
           private String city;
           private String state;
           private String cardType;
           private String cardNumber;
           private String cardExpDate;
           private String fname;
           private String lname;
           public void setAddress(String inAddress) {
            address = inAddress;
           }
           public void setCity(String inCity) {
            city = inCity;
           }
           public void setState(String inState) {
            state = inState;
           }
           public void setFName(String inFName) {
            fname = inFName;
           }
           public void setLName(String inLName) {
            lname = inLName;
           }
           public void setCardType(String inCardType) {
            cardType = inCardType;
           }
           public void setCardNumber(String inCardNumber) {
            cardNumber = inCardNumber;
           }
           public void setCardExpDate(String inCardExpDate) {
            cardExpDate = inCardExpDate;
           }
           public boolean saveCustomerData() {
            Address objAddress;
            Account objAccount;
            CreditCard objCreditCard;
            /*
             client is transparent from the following
             set of subsystem related operations.
            */
            boolean validData = true;
            String errorMessage = "";
            objAccount = new Account(fname, lname);
            if (objAccount.isValid() == false) {
             validData = false;
             errorMessage = "Invalid FirstName/LastName";
            }
            objAddress = new Address(address, city, state);
            if (objAddress.isValid() == false) {
             validData = false;
             errorMessage = "Invalid Address/City/State";
            }
            objCreditCard = new CreditCard(cardType, cardNumber, cardExpDate);
            if (objCreditCard.isValid() == false) {
             validData = false;
             errorMessage = "Invalid CreditCard Info";
            }
            if (!validData) {
             System.out.println(errorMessage);
             return false;
            }
            if (objAddress.save() && objAccount.save() && objCreditCard.save()) {
             return true;
            } else {
             return false;
            }
           }
          }

             CustomerFacade類以saveCustomData方法的形式提供了業務層次上的服務。客戶AccountManager不是直接和子系統 的每一個組件交互,而是使用了由CustomFacade對象提供的驗證和保存客戶數據的更高層次、更簡單的接口(Figure7).

          ?
          Figure7: Class Association with the Fa?ade Class in Place 。

            在新的設計中,為了驗證和保存客戶數據,客戶需要:

            (1) 建立或獲得外觀對象CustomFacade的一個實例。

            (2) 傳遞數據給CustomFacade實例進行驗證和保存。

            (3) 調用CustomFacade實例上的saveCustomData方法。

            CustomFacade處理創建子系統中必要的對象并且調用這些對象上相應的驗證、保存客戶數據的方法這些細節問題。客戶不再需要直接訪問任何的子系統中的對象。

            Figure8展示了新的設計的消息流圖:

          ?
          Figure 22.8: In the Revised Design, Clients Interact with the Fa?ade Instance to Interface with the Subsystem

            重要提示

            下面是應用外觀模式的注意事項:

            (1) 在設計外觀時,不需要增加額外的功能。

            (2) 不要從外觀方法中返回子系統中的組件給客戶。例如:有一個下面的方法:

            CreditCard getCreditCard()

            會報漏子系統的細節給客戶。應用就不能從應用外觀模式中取得最大的好處。

            (3)應用外觀的目的是提供一個高層次的接口。因此,外觀方法最適合提供特定的高層次的業務服務,而不是進行底層次的單獨的業務執行。
          posted on 2006-09-03 00:07 Alex 閱讀(500) 評論(0)  編輯  收藏 所屬分類: design
          主站蜘蛛池模板: 论坛| 资阳市| 衡山县| 讷河市| 林甸县| 郸城县| 广南县| 安乡县| 榆树市| 渭南市| 宁武县| 黎平县| 阜阳市| 宁晋县| 寿光市| 昌江| 汕尾市| 双江| 始兴县| 仙居县| 太仓市| 大丰市| 柳河县| 济宁市| 玛曲县| 高尔夫| 洱源县| 襄汾县| 靖远县| 通道| 澄城县| 东安县| 南川市| 满洲里市| 浮梁县| 米林县| 巫山县| 收藏| 盐源县| 民权县| 盐山县|