大话设计模式
字体: 16 + -

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