大B:“我给你举个例子来说明吧!”
小A:“嗯。好的。”
大B:“让我们建立一个应用:1、接受客户的详细资料(账户、地址和信用卡信息)2、验证输入的信息3、保存输入的信息到相应的文件中。这个应用有三个类:Account、Address和CreditCard。每一个类都有自己的验证和保存数据的方法。”
Listing1:AccountClass
publicclassAccount{
StringfirstName;
StringlastName;
finalStringACCOUNTDATAFILE=“AccountData.txt”;
publicAccount(Stringfname,Stringlname){
firstName=fname;
lastName=lname;
}
publicbooleanisValid(){
/*
Letsgowithsimplervalidation
heretokeeptheexamplesimpler.
*/
}
publicbooleansave(){
FileUtilfutil=newFileUtil();
StringdataLine=getLastName()+,+getFirstName();
returnfutil.writeToFile(ACCOUNTDATAFILE,dataLine,true,true);
}
publicStringgetFirstName(){
returnfirstName;
}
publicStringgetLastName(){
returnlastName;
}
}
Listing2:AddressClass
publicclassAddress{
Stringaddress;
Stringcity;
Stringstate;
finalStringADDRESSDATAFILE=“Address.txt”;
publicAddress(Stringadd,Stringcty,Stringst){
address=add;
city=cty;
state=st;
}
publicbooleanisValid(){
/*
Theaddressvalidationalgorithm
couldbeplexinreal-world
applications.
Letsgowithsimplervalidation
heretokeeptheexamplesimpler.
*/
if(getState().trim().length()(2)
returnfalse;
returntrue;
}
publicbooleansave(){
FileUtilfutil=newFileUtil();
StringdataLine=getAddress()+,“+getCity()+”,+getState();
returnfutil.writeToFile(ADDRESSDATAFILE,dataLine,true,true);
}
publicStringgetAddress(){
returnaddress;
}
publicStringgetCity(){
returncity;
}
publicStringgetState(){
returnstate;
}
}
Listing3:CreditCardClass
publicclassCreditCard{
StringcardType;
StringcardNumber;
StringcardExpDate;
finalStringCCDATAFILE=“CC.txt”;
publicCreditCard(StringccType,StringccNumber,
StringccExpDate){
cardType=ccType;
cardNumber=ccNumber;
cardExpDate=ccExpDate;
}
publicbooleanisValid(){
/*
Letsgowithsimplervalidation
heretokeeptheexamplesimpler.
*/
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);
}
returnfalse;
}
publicbooleansave(){
FileUtilfutil=newFileUtil();
StringdataLine=getCardType()+,“+getCardNumber()+”,+getCardExpDate();
returnfutil.writeToFile(CCDATAFILE,dataLine,true,true);
}
publicStringgetCardType(){
returncardType;
}
publicStringgetCardNumber(){
returncardNumber;
}
publicStringgetCardExpDate(){
returncardExpDate;
}
}
Listing4:ClientAccountManagerClass
publicclassAccountManagerextendsJFrame{
publicstaticfinal-0*963Stringnewline=“\n”;
publicstaticfinalStringVALIDATES**E=“Validate&Save”;
publicAccountManager(){
super(“FacadePattern-Example”);
cmbCardType=newJComboBox();
cmbCardType.addItem(AccountManager.VISA);
cmbCardType.addItem(AccountManager.MASTER);
cmbCardType.addItem(AccountManager.DISCOVER);
//Createbuttons
JButtonvalidateSaveButton=newJButton(AccountManager.VALIDATES**E);
}
publicStringgetFirstName(){
returntxtFirstName.getText();
}
}//EndofclassAccountManager
当客户AccountManage运行的时候,展示的用户接口如下:
图大B:“在这个例子中应用外观模式是一个很好的设计,它可以降低客户和子系统组件(Address、Account和CreditCard)之间的耦合度。应用外观模式,定义一个外观类CustomerFacade(Figure6andListing5)。它为由客户数据处理类(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()
publicclassCustomerFacade{
privateStringaddress;
privateStringcity;
privateStringstate;
privateStringcardType;
privateStringcardNumber;
privateStringcardExpDate;
privateStringfname;
privateStringlname;
publicvoidsetAddress(StringinAddress){
address=inAddress;
}
publicvoidsetCity(StringinCity){
city=inCity;
}
publicvoidsetState(StringinState){
state=inState;
}
publicvoidsetFName(StringinFName){
fname=inFName;
}
publicvoidsetLName(StringinLName){
lname=inLName;
}
publicvoidsetCardType(StringinCardType){
cardType=inCardType;
}
publicvoidsetCardNumber(StringinCardNumber){
cardNumber=inCardNumber;
}
publicvoidsetCardExpDate(StringinCardExpDate){
cardExpDate=inCardExpDate;
}
publicbooleansaveCustomerData(){
AddressobjAddress;
AccountobjAccount;
CreditCardobjCreditCard;
/*
clientistransparentfromthefollowing
setofsubsystemrelatedoperations.
*/
booleanvalidData=true;
StringerrorMessage=;
objAccount=newAccount(fname,lname);
if(objAccount.isValid()……false){
validData=false;
errorMessage=“InvalidFirstName/LastName”;
}
objAddress=newAddress(address,city,state);
if(objAddress.isValid()……false){
validData=false;
errorMessage=“InvalidAddress/City/State”;
}
objCreditCard=newCreditCard(cardType,cardNumber,cardExpDate);
if(objCreditCard.isValid()……false){
validData=false;
errorMessage=“InvalidCreditCardInfo”;
}
if(!validData){
System.out.println(errorMessage);
returnfalse;
}
if(objAddress.save()&objAccount.save()&objCreditCard.save()){
returntrue;
}else{
returnfalse;
}
}
}
大B:“CustomerFacade类以saveCustomData方法的形式提供了业务层次上的服务。客户AccountManager不是直接和子系统的每一个组件交互,而是使用了由CustomFacade对象提供的验证和保存客户数据的更高层次、更简单的接口。”
B:“在新的设计中,为了验证和保存客户数据,客户需要:1、建立或获得外观对象CustomFacade的一个实例。2、传递数据给CustomFacade实例进行验证和保存。3、调用CustomFacade实例上的saveCustomData方法。CustomFacade处理创建子系统中必要的对象并且调用这些对象上相应的验证、保存客户数据的方法这些细节问题。客户不再需要直接访问任何的子系统中的对象。”
小A:“师兄,应用外观模式有哪些注意事项?”
大B:“应用外观模式要注意以下事项:1、在设计外观时,不需要增加额外的功能。2、不要从外观方法中返回子系统中的组件给客户。例如:有一个下面的方法:CreditCardgetCreditCard()会报漏子系统的细节给客户。应用就不能从应用外观模式中取得最大的好处。3、应用外观的目的是提供一个高层次的接口。因此,外观方法最适合提供特定的高层次的业务服务,而不是进行底层次的单独的业务执行。”
小A:“明白。我记住了!”