java随记

坚持就是胜利!

 

访问者模式实战:构建通用的数据库插入操作


在做一些简单的JDBC的API应用时,就老想只用一个方法向数据库不同的表做插入操作,省得
用一大堆的insert语句。访问者模式可以实现对未知的类进行操作,于是就用了这个简化了的模
式的实现方案。请高手指正。 在使用访问者模式之前先叙述一点概念性的东西。
静态类型的概念:变量被申明时的类型。实际类型:变量的实际类型。
比如 Object object=new String(); object静态类型是Object,实际类型是String.
观察者模式是一个比较难理解的模式,在理解观察者模式之前当然应该先理解双重分派的概念。
java语言支持静态的多分派跟动态的单分派。java通重载支持静态的多分派。书上的例子:
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
原因就是对两次ride方法的调用传入的参量不同,但是它们的静态类型是一样的,都是 Horse;
这个过程在编译时期就完成了。
java通过方法置换支持动态分派。比如 String s1="ab"; Object o=s1+"c"; String s="abc";
o.equals(s) 打印true  o.equals()方法执行的是String类的equals()方法.java调用对象的
真实类型的方法,这就是动态分派。
双重分派:
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);
   }  
}
方法的调用Visitor v=new ConcreteVisitor(); v.processString(new String("tt"));
v.processString()方法在调用的时候会检察v的真实类型,调用真实类型的方法,这个时候就
发生了一动态的单分派过程.当子类调用超类的方法的时候明显的根据instanceof判断的真实类
型去执行不同的方法,又发生了一次动态分派的过程.这个就是双重分派的实现。这种方法实现的
程序比较冗长和容易出错.
“返传球”方案:
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(){
     ...
    }
 }
方法的调用:
Visitor v = new ConcreteVisitor();
Wrapper wrapper= new WrapperString();
wrapper.processString(v);
当wrapper.processString()方法执行的时候会检察wrapper的真实类型,这个就产生了一次
动态单分派,processString()里面的语句v.processString()在执行的时候也会检察v的真
实类型,动态双重分派就发生了。
访问者模式的核心就是“返传球“方案的双重分派。其示意性类图:(注:虚线箭头划错了)



visitor.jpg

在一个方法内实现向不同的表插入不同数据的具体实现方案(简化了的):因为整个方案里只需
要一个访问者对象,因此使用简化了的访问者模式。因为java基本类型及对应的类是不变模式的
实现:因此包装一下这些基本类型和类并实现访问者模式需要的方法。
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 + "'";
    }


}

具体访问者的实现:
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();
    }
}

具体应用类的实现:

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);
       


    }
}

程序打印结果:

insert into cutomer (name,age,fuctiontime) values(null,1,'Sat Aug 12 13:46:58 CST 2006')

这个输出是满足MSSQL执行插入的语法要求的.虽然这样就实现了想要的结果,
但是insertData(String tablename, List columNameCollection, List values) 方法在每次调
用的时候需要输入表名跟该表的列的集合,还是很麻烦,不尽人意,而且不同的数
据库的表名是不一样的,因此最好用配置文件来解决这一个问题.

欢迎加入QQ群:30406099 

 


 

posted on 2006-08-14 14:39 傻 瓜 阅读(2232) 评论(2)  编辑  收藏 所属分类: 杂项

评论

# re: 访问者模式实战:构建通用的数据库插入操作 2006-08-14 15:08 伯伯

晕了!

还是下面这个够清楚
Proxy Visitor Pattern
http://www.hibernate.org/280.html

  回复  更多评论   

# re: 访问者模式实战:构建通用的数据库插入操作 2006-10-08 12:29 我的


  回复  更多评论   


只有注册用户登录后才能发表评论。


网站导航:
 

导航

统计

常用链接

留言簿(5)

我参与的团队

随笔分类

随笔档案

文章分类

友情链接

搜索

积分与排名

最新评论

阅读排行榜

评论排行榜