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)所组成的子系统提供一个高层次的、简单的接口。