大B:“我给你举个例子来说明吧!”
小A:“嗯。好的。”
大B:“让我们建立一个应用:1、接受客户的详细资料(账户、地址和信用卡信息)2、验证输入的信息3、保存输入的信息到相应的文件中。这个应用有三个类:Account、Address和CreditCard。每一个类都有自己的验证和保存数据的方法。”
Listing1:AccountClass
public class Account{
String firstName;
String lastName;
final String ACCOUNTDATAFILE=“AccountData。txt”;
public Account(String fname,String lname){
firstName=fname;
lastName=lname;
}
public boolean isValid(){
/*
Lets go with simpler validation
here to keep the example simpler。
*/
}
public boolean save(){
FileUtil futil=new FileUtil();
String dataLine=getLastName() , getFirstName();
return futil。writeToFile(ACCOUNTDATAFILE,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 ADDRESSDATAFILE=“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。
Lets 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(ADDRESSDATAFILE,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 CCDATAFILE=“CC。txt”;
public CreditCard(String ccType,String ccNumber,
String ccExpDate){
cardType=ccType;
cardNumber=ccNumber;
cardExpDate=ccExpDate;
}
public boolean isValid(){
/*
Lets 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(CCDATAFILE,dataLine,true,true);
}
public String getCardType(){
return cardType;
}
public String getCardNumber(){
return cardNumber;
}
public String getCardExpDate(){
return cardExpDate;
}
}
Listing4:Client AccountManager Class
public class AccountManager extends JFrame{
public static final-0*963String newline=“\n”;
public static final String VALIDATESAVE=“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。VALIDATESAVE);
}
public String getFirstName(){
return txtFirstName。getText();
}
}//End of class AccountManager
当客户AccountManage运行的时候,展示的用户接口如下:
图大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()
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对象提供的验证和保存客户数据的更高层次、更简单的接口。”
B:“在新的设计中,为了验证和保存客户数据,客户需要:1、建立或获得外观对象CustomFacade的一个实例。2、传递数据给CustomFacade实例进行验证和保存。3、调用CustomFacade实例上的saveCustomData方法。CustomFacade处理创建子系统中必要的对象并且调用这些对象上相应的验证、保存客户数据的方法这些细节问题。客户不再需要直接访问任何的子系统中的对象。”
小A:“师兄,应用外观模式有哪些注意事项?”
大B:“应用外观模式要注意以下事项:1、在设计外观时,不需要增加额外的功能。2、不要从外观方法中返回子系统中的组件给客户。例如:有一个下面的方法:CreditCard getCreditCard()会报漏子系统的细节给客户。应用就不能从应用外观模式中取得最大的好处。3、应用外观的目的是提供一个高层次的接口。因此,外观方法最适合提供特定的高层次的业务服务,而不是进行底层次的单独的业务执行。”
小A:“明白。我记住了!”