zoukankan      html  css  js  c++  java
  • 解决实体类噩梦:联合实体类(Java反射+泛型实际应用)

           小菜提到的实体类,即项目中业务或者数据库表的映射,貌似也可以称为模型,不同的语言中叫法不同吧!!

           举个例子,比如在某个Web页面中,表单上有大量的数据需要提交,如果是初学者,很可能这样接收参数:

           String param1;String param2;String param3;……

           这样做的坏处很多,比如:代码会显得很乱,可能会出现大量重复代码,最主要的就是没有做到面向对象的“封装性”,导致程序不容易维护。

           由此,聪明的程序员们提出了实体类的概念,也就是用类来封装业务所需要的数据。

           public class User {

           private String uid;

           private String pwd;

           public String getUid() {

                  return uid;

           }

           public void setUid(String uid) {

                  this.uid = uid;

           }

           …..

           }

           这样一来,我们在保存数据时,只需创建一个对象,然后通过“.”的方式来访问对象的属性,提高扩展性、提高复用性、代码简洁等等好处不言而喻。

           在实际使用中,实体类往往是和某个业务或者数据库表相对应的,看起来很简单,但随着需求的复杂化,业务和业务之间可能会交叉,表和表之间可能会联合查询。

           这样一来,以前一一对应的实体类,便无法满足需求,因为某个实体类中可能找不到我们需要的属性,但是它却在另一个实体类中,而我们又不想随便在某个实体类中添加一个毫不相关的属性,因为这样做可能会打破类的职责单一原则。

           因此,我们不得不再新建一个实体类ClassAAndClassB,这个实体类包含了类A和类B的所有属性,对于稍有经验的程序员来说,这绝对是个噩梦,因为组合的可能性是在是太多,而且可能是很多个实体组合,等待我们的将是无数的实体类,导致程序混乱不堪。

           小菜一直苦于此事,今天终于通过Java的反射和泛型写了一个“联合实体类”。

           通过这个联合实体类,可以把任意多个实体类融合成一个实体类。

    联合实体类代码:

      1 import java.lang.reflect.Method;
      2 import java.util.List;
      3 
      4 /**
      5  * 联合实体类
      6  * @author 杨元
      7  *
      8  */
      9 public class UniteEntity {
     10     
     11     //联合实体对象集合
     12     List<Object> entitys = null;
     13     //方法名称
     14     String fnName = "";
     15     //方法对象
     16     Method method = null;
     17     
     18     /**
     19      * 构造方法
     20      * @param entitys 需要联合的实体对象集合
     21      */
     22     public UniteEntity(List<Object> entitys){
     23         this.entitys = entitys;
     24     }
     25     
     26     /**
     27      * 获取某个取值方法
     28      * @param fnName 方法名称
     29      * @return 该取值方法返回值类型
     30      */
     31     public Class getFunction(String fnName){
     32         //保存方法名称
     33         this.fnName = fnName;
     34         //查找方法
     35         Method m = findMethod();
     36         //判断方法是否存在
     37         if(m != null){
     38             //获取目标方法的返回值类型
     39             Class type = m.getReturnType();
     40             //保存取值方法对象
     41             method = m;
     42             //返回该取值方法返回值类型
     43             return type;
     44         }else{
     45             return null;
     46         }
     47     }
     48     
     49     /**
     50      * 获取某个赋值方法
     51      * @param fnName 方法名称
     52      * @return 该赋值方法参数类型
     53      */
     54     public Class setFunction(String fnName){
     55         //保存方法名称
     56         this.fnName = fnName;
     57         //查找方法
     58         Method m = findMethod();
     59         //判断方法是否存在
     60         if(m != null){
     61             //获取目标方法的参数类型
     62             Class type = m.getParameterTypes()[0];
     63             //保存赋值方法对象
     64             method = m;
     65             //返回该赋值方法参数类型
     66             return type;
     67         }else{
     68             return null;
     69         }
     70     }
     71     
     72     /**
     73      * 调用某个方法,为属性赋值
     74      * @param <T> 赋值方法的参数类型
     75      * @param c
     76      * @param value 值内容
     77      */
     78     public <T> void setValue(Class<T> c,T value){
     79         //遍历实体类集合
     80         for(Object o : entitys){
     81             //出错继续执行
     82             try{
     83                 method.invoke(o, value);
                break;
    84 }catch(Exception ex){} 85 } 86 } 87 88 /** 89 * 调用某个方法,取得属性的值 90 * @param <T> 取值方法的返回值类型 91 * @param c 92 * @return 取得值的内容 93 */ 94 public <T> T getValue(Class<T> c){ 95 //遍历实体类集合 96 for(Object o : entitys){ 97 //出错继续运行 98 try{ 99 //由于invoke返回的是Object类型,因此要强制转换成T类型 100 return (T)method.invoke(o); 101 }catch(Exception ex){} 102 } 103 return null; 104 } 105 106 /** 107 * 从实体对象集合中查找某个方法 108 * @return 方法对象 109 */ 110 private Method findMethod(){ 111 //遍历集合,寻找方法 112 for(Object o : entitys){ 113 //保证出错能继续运行 114 try{ 115 //获取对象所有公有方法 116 Method[] methods = o.getClass().getMethods(); 117 118 //遍历方法 119 for(Method m : methods){ 120 //匹配是否有目标方法 121 if(fnName.equals(m.getName())){ 122 //返回方法对象 123 return m; 124 } 125 } 126 }catch(Exception ex){} 127 } 128 return null; 129 } 130 }

    调用方法:

     1 //创建一个对象集合
     2 List<Object> list = new ArrayList<Object>();
     3 
     4 //将需要融合的实体类填入集合
     5 list.add(new User());
     6 list.add(new Enterprise());
     7 
     8 //创建联合实体类对象
     9 UniteEntity ue = new UniteEntity(list);
    10 
    11 int i = 109;
    12 
    13 //调用实体类中方法名为setEnno的方法(赋值方法),并给一个参数i
    14 ue.setValue(ue.setFunction("setEnno"), i);
    15 //调用实体类中方法名为getEnno的方法(取值方法),并打印返回值
    16 System.out.println(ue.getValue(ue.getFunction("getEnno")));

    说明:

           用法很简单,创建联合实体对象的时候必须传入需要融合的实体对象集合。

           如果想调用的方法是取值方法,则先调用联合实体对象的getFunction方法,参数是方法的名称,一定要写对!!最好是复制!!这个步骤会查找到指定的方法,并且确定该方法的返回值类型,然后把getFunction方法的返回值作为参数,调用联合实体对象的getValue方法,即可取得属性值。

           如果想调用的方法是赋值方法,则先调用联合实体对象的setFunction方法,同理,该方法会确定参数的类型,把setFunction方法的返回值作为参数,调用联合实体对象的setValue方法,再加上需要赋给的值,即可给属性赋值。

           由于使用了泛型技术,所以本类比较安全、稳定。调用赋值方法时,如果传入的值和方法的参数类型不同,直接赋值失败,不会抛出异常;调用取值方法时,直接对取出来的值进行强制类型转换即可,无需验证数据类型(例如:int[] items = (int[])ue.getValue(ue.getFunction("getEmp"));)。

    注意事项:

           使用本类肯定会降低程序效率,慎重使用。

           本类只支持带有一个参数的属性赋值方法。

           如果多个实体类中有重复的方法名称,则默认使用的是在集合中靠前的那个实体类的方法。

    写在后面的话:

           本文只是提供一种思路,肯定不是最好的解决方案,也不一定能满足读者的需求,高手勿喷。。。

    附:完整演示代码

           点我下载

  • 相关阅读:
    程序员的7中武器
    需要强化的知识
    微软中国联合小i推出MSN群Beta 不需任何插件
    XML Notepad 2006 v2.0
    Sandcastle August 2006 Community Technology Preview
    [推荐] TechNet 广播 SQL Server 2000完结篇
    《太空帝国 4》(Space Empires IV)以及 xxMod 英文版 中文版 TDM Mod 英文版 中文版
    IronPython 1.0 RC2 更新 1.0.60816
    Microsoft .NET Framework 3.0 RC1
    《Oracle Developer Suite 10g》(Oracle Developer Suite 10g)V10.1.2.0.2
  • 原文地址:https://www.cnblogs.com/iyangyuan/p/3029814.html
Copyright © 2011-2022 走看看