大B:“我给你举个例子来说明吧。”
小A:“嗯。好的。”
大B:“让我们建立一个应用: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; } }
图4-3 验证并保存客户数据
大B:“建立一个客户AccountManager,它提供用户输入数据的用户界面。”
Listing4: Client AccountManager Class public class AccountManager extends JFrame { public static final -0*963String 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运行的时候,展示的用户接口如下:
图4-4 用户接口
大B:“为了验证和保存输入的数据,客户AccountManager需要:1、建立Account、Address和CreditCard对象。 2、用这些对象验证输入的数据3、用这些对象保存输入的数据。”
图4-5是对象间的交互顺序图:
图4-5 对象间的交互顺序图
大B:“在这个例子中应用外观模式是一个很好的设计,它可以降低客户和子系统组件(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()
图4-6 外观类
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; } } }
大B:“CustomerFacade类以saveCustomData方法的形式提供了业务层次上的服务。客户AccountManager不是直接和子系统的每一个组件交互,而是使用了由CustomFacade对象提供的验证和保存客户数据的更高层次、更简单的接口(如图4-7所示)。”
图4-7 验证和保存客户数据
大B:“在新的设计中,为了验证和保存客户数据,客户需要:1、建立或获得外观对象CustomFacade的一个实例。2、传递数据给CustomFacade实例进行验证和保存。3、调用CustomFacade实例上的saveCustomData方法。CustomFacade处理创建子系统中必要的对象并且调用这些对象上相应的验证、保存客户数据的方法这些细节问题。客户不再需要直接访问任何的子系统中的对象。”
图4-8展示了新的设计的消息流图:
图4-8 新的设计的消息流图