訪問者模式實(shí)戰(zhàn):構(gòu)建通用的數(shù)據(jù)庫(kù)插入操作
在做一些簡(jiǎn)單的JDBC的API應(yīng)用時(shí),就老想只用一個(gè)方法向數(shù)據(jù)庫(kù)不同的表做插入操作,省得
用一大堆的insert語(yǔ)句。訪問者模式可以實(shí)現(xiàn)對(duì)未知的類進(jìn)行操作,于是就用了這個(gè)簡(jiǎn)化了的模
式的實(shí)現(xiàn)方案。請(qǐng)高手指正。 在使用訪問者模式之前先敘述一點(diǎn)概念性的東西。
靜態(tài)類型的概念:變量被申明時(shí)的類型。實(shí)際類型:變量的實(shí)際類型。
比如 Object object=new String(); object靜態(tài)類型是Object,實(shí)際類型是String.
觀察者模式是一個(gè)比較難理解的模式,在理解觀察者模式之前當(dāng)然應(yīng)該先理解雙重分派的概念。
java語(yǔ)言支持靜態(tài)的多分派跟動(dòng)態(tài)的單分派。java通重載支持靜態(tài)的多分派。書上的例子:
public class Mozi {
???
??? public void ride(Horse h){
??????? System.out.println("ridding a horse");
??? }
??? public void ride(WhiteHorse w){
??????? System.out.println("ridding a white horse");
??? }
??? public void ride(BlackHorse b){
??????? System.out.println("rdding a black horse");
??? }
??? public static void main(String[] args){
????? Mozi mozi=new Mozi();
????? Horse w=new WhiteHorse();
????? Horse b=new BlackHorse();
????? mozi.ride(w);
????? mozi.ride(b);
??? }
}?
程序打印輸出:
ridding a horse
ridding a horse
原因就是對(duì)兩次ride方法的調(diào)用傳入的參量不同,但是它們的靜態(tài)類型是一樣的,都是 Horse;
這個(gè)過程在編譯時(shí)期就完成了。
java通過方法置換支持動(dòng)態(tài)分派。比如 String s1="ab"; Object o=s1+"c"; String s="abc";
o.equals(s) 打印true? o.equals()方法執(zhí)行的是String類的equals()方法.java調(diào)用對(duì)象的
真實(shí)類型的方法,這就是動(dòng)態(tài)分派。
雙重分派:
public abstract class Vistor{
protected void processStrig(Object e){
?if(e instanceof String){
???? String tmp=(String) e;
???? String need="'"+e+"'";
???? System.out.println(nedd);
?? }else if(e instanceof Integer){
?????? String need=e.toString();
?????? System.out.println(need);
??? }else if(e instanceof Date){
???????????? Date tmp=(Date) e;
???????????? String need="'"+tmp.toString()+"'";
??????? }
????? ....
??? }
}
public class ConcreteVisitor extends Visitor{
protected void processString(Object e){
???? super.processString(e);
?? }??
}
方法的調(diào)用Visitor v=new ConcreteVisitor(); v.processString(new String("tt"));
v.processString()方法在調(diào)用的時(shí)候會(huì)檢察v的真實(shí)類型,調(diào)用真實(shí)類型的方法,這個(gè)時(shí)候就
發(fā)生了一動(dòng)態(tài)的單分派過程.當(dāng)子類調(diào)用超類的方法的時(shí)候明顯的根據(jù)instanceof判斷的真實(shí)類
型去執(zhí)行不同的方法,又發(fā)生了一次動(dòng)態(tài)分派的過程.這個(gè)就是雙重分派的實(shí)現(xiàn)。這種方法實(shí)現(xiàn)的
程序比較冗長(zhǎng)和容易出錯(cuò).
“返傳球”方案:
public abstract class Vistor{
?? public abstract String processStrig(Object e);
}
public class ConcreteVisitor extends Visitor{
? public String processString(WrapperString e){
??? String tmp= t.toString();
??? System.out.println(tmp);
?? }??
? public String processInteger(WrapperInteger e){
??? String tmp=e.toString();
??? System.out.println(tmp);
?? }
}
public class abstract Wrapper{
? public abstract String processString(Vistor v);
}
public class WrapperString extends Wrapper{
? public String processString(Vistor v){
??? v.processString(this);
?? }
? public String toString(){
?? ...
?? }
}
public class WrapperInteger extends Wrapper{
??? public String processInteger(Visitor v){
???? v.processString(this);
??? }
??? public String toString(){
???? ...
??? }
?}
方法的調(diào)用:
Visitor v = new ConcreteVisitor();
Wrapper wrapper= new WrapperString();
wrapper.processString(v);
當(dāng)wrapper.processString()方法執(zhí)行的時(shí)候會(huì)檢察wrapper的真實(shí)類型,這個(gè)就產(chǎn)生了一次
動(dòng)態(tài)單分派,processString()里面的語(yǔ)句v.processString()在執(zhí)行的時(shí)候也會(huì)檢察v的真
實(shí)類型,動(dòng)態(tài)雙重分派就發(fā)生了。
訪問者模式的核心就是“返傳球“方案的雙重分派。其示意性類圖:(注:虛線箭頭劃錯(cuò)了)
在一個(gè)方法內(nèi)實(shí)現(xiàn)向不同的表插入不同數(shù)據(jù)的具體實(shí)現(xiàn)方案(簡(jiǎn)化了的):因?yàn)檎麄€(gè)方案里只需
要一個(gè)訪問者對(duì)象,因此使用簡(jiǎn)化了的訪問者模式。因?yàn)閖ava基本類型及對(duì)應(yīng)的類是不變模式的
實(shí)現(xiàn):因此包裝一下這些基本類型和類并實(shí)現(xiàn)訪問者模式需要的方法。
public abstract class Wrapper {
??? public Wrapper() {
??? }
??? public abstract String action(Visitor visitor);
}
包裝Date類:
import java.util.Date;
public class WrapperDate extends Wrapper {
??? private Date date;
??? public WrapperDate(Date date) {
??????? this.date=date;
??? }
??? public String action(Visitor visitor){
???????? return( visitor.visit(this));
??? }
??? public String toString(){
??????? if (date==null){
??????????? return "null";
??????? }
??????? return "'"+date.toString()+"'";
??? }
}
包裝Integer類:
public class WrapperInteger extends Wrapper {
??? private Integer value;
??? public WrapperInteger(Integer value) {
??????? this.value=value;
??? }
??? public WrapperInteger(int value){
??????? this.value=new Integer(value);
??? }
??? public WrapperInteger(String value){
????? this.value=new Integer(value);
??? }
??? public String action(Visitor visitor){
?????? return( visitor.visit(this));
??? }
??? public String toString(){
??????? if(value==null){
??????????? return "null";
??????? }
??????? return value.toString();
??? }
}
包裝String類:
public class WrapperString extends Wrapper {
??? private String wrapper;
??? public WrapperString( String wrapper) {
??????? this.wrapper = wrapper;
??? }
??? public WrapperString( char[] wrap) {
??????? wrapper = new String(wrap);
??? }
??? public String action(Visitor visitor) {
??????? return (visitor.vistit(this));
??? }
??? public String toString() {
??????? if(wrapper==null){
??????????? return "null";
??????? }
??????? return "'" + wrapper + "'";
??? }
}
具體訪問者的實(shí)現(xiàn):
public class Visitor {
??? public Visitor() {
??? }
??? public String vistit(WrapperString wrap){
?????? return wrap.toString();
??? }
??? public String visit(WrapperInteger value){
??????? return value.toString();
??? }
??? public String visit(WrapperDate date){
??????? return date.toString();
??? }
}
具體應(yīng)用類的實(shí)現(xiàn):
import java.util.*;
public class Test {
??? private Visitor visitor = new Visitor();
??? public Test() {
??? }
??? public Visitor getVisitor() {
??????? return visitor;
??? }
??
??? public int insertData(String tablename, List columNameCollection,
????????????????????????? List values) {
??????? StringBuffer query = new StringBuffer("insert into " + tablename + " (");
??????? int count = 0;
??????? for (Iterator it = columNameCollection.iterator(); it.hasNext(); ) {
??????????? String columName = (String) it.next();
??????????? query.append(columName);
??????????? query.append(",");
??????? }
??????? query.deleteCharAt(query.length() - 1);
??????? query.append(") values(");
??????? for (Iterator it = values.iterator(); it.hasNext(); ) {
??????????? Wrapper wrapper = (Wrapper) it.next();
??????????? String tmp = wrapper.action(getVisitor());
??????????? query.append(tmp);
??????????? query.append(",");
??????? }
??????? query.deleteCharAt(query.length() - 1);
??????? query.append(")");
??????? System.out.println(query.toString());
??????? return count;
??? }
??? public static void main(String[] args) {
??????? Test test = new Test();
??????? String tableName = "cutomer";
??????? List columNameCollection = new ArrayList();
??????? String columName = "name";
??????? String columAge = "age";
??????? String columFunctionTime="fuctiontime";
??????? columNameCollection.add(columName);
??????? columNameCollection.add(columAge);
??????? columNameCollection.add(columFunctionTime);
??????? List values = new ArrayList();
??????? String name=null;
??????? Wrapper wrapper1 = new WrapperString(name);
??????? Wrapper wrapper2 = new WrapperInteger(1);
??????? Wrapper wrapper3= new WrapperDate(new java.util.Date());
??????? values.add(wrapper1);
??????? values.add(wrapper2);
??????? values.add(wrapper3);
??????? test.insertData(tableName,columNameCollection,values);
???????
??? }
}
程序打印結(jié)果:
insert into cutomer (name,age,fuctiontime) values(null,1,'Sat Aug 12 13:46:58 CST 2006')
這個(gè)輸出是滿足MSSQL執(zhí)行插入的語(yǔ)法要求的.雖然這樣就實(shí)現(xiàn)了想要的結(jié)果,
但是insertData(String tablename, List columNameCollection, List values) 方法在每次調(diào)
用的時(shí)候需要輸入表名跟該表的列的集合,還是很麻煩,不盡人意,而且不同的數(shù)
據(jù)庫(kù)的表名是不一樣的,因此最好用配置文件來(lái)解決這一個(gè)問題.
歡迎加入QQ群:30406099?
?
?
posted on 2006-08-14 14:39 傻 瓜 閱讀(2387) 評(píng)論(2) 編輯 收藏 所屬分類: 雜項(xiàng)