第31章
大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:“明白。我记住了!”