Java 为我的类中使用的通用pojo建模

Java 为我的类中使用的通用pojo建模,java,design-patterns,pojo,dto,Java,Design Patterns,Pojo,Dto,我正在尝试创建一个像通用POJO一样工作的对象,因为我必须通过不同的对象传递它,并且我需要一个接口,它们可以通过该接口访问它的属性 目前,我使用一个具有getField方法的基本对象执行此操作,在该方法中,我输入参数的名称,然后通过反射获得参数,如下所示: public abstract class BasePOJO{ public Object getField(String fieldName){ try { return this.get

我正在尝试创建一个像通用POJO一样工作的对象,因为我必须通过不同的对象传递它,并且我需要一个接口,它们可以通过该接口访问它的属性

目前,我使用一个具有getField方法的基本对象执行此操作,在该方法中,我输入参数的名称,然后通过反射获得参数,如下所示:

public abstract class BasePOJO{

    public Object getField(String fieldName){

        try {
            return this.getClass().getField(fieldName).get(this);

        } catch (NoSuchFieldException ex) {
            Logger.getLogger(BaseRequest.class.getName()).log(Level.SEVERE, null, ex);
        } catch (SecurityException ex) {
            Logger.getLogger(BaseRequest.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IllegalArgumentException ex) {
            Logger.getLogger(BaseRequest.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            Logger.getLogger(BaseRequest.class.getName()).log(Level.SEVERE, null, ex);
        }

        return null;
    }
}
public class CredentialsPOJO extends BasePOJO{
    public String username;
    public String password;
}
credentialsPojo.getField("username");
String name = pojo.getProperty("name");
Integer age = pojo.getProperty("age");
我用它来扩展类,如下所示:

public abstract class BasePOJO{

    public Object getField(String fieldName){

        try {
            return this.getClass().getField(fieldName).get(this);

        } catch (NoSuchFieldException ex) {
            Logger.getLogger(BaseRequest.class.getName()).log(Level.SEVERE, null, ex);
        } catch (SecurityException ex) {
            Logger.getLogger(BaseRequest.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IllegalArgumentException ex) {
            Logger.getLogger(BaseRequest.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            Logger.getLogger(BaseRequest.class.getName()).log(Level.SEVERE, null, ex);
        }

        return null;
    }
}
public class CredentialsPOJO extends BasePOJO{
    public String username;
    public String password;
}
credentialsPojo.getField("username");
String name = pojo.getProperty("name");
Integer age = pojo.getProperty("age");
并调用如下属性:

public abstract class BasePOJO{

    public Object getField(String fieldName){

        try {
            return this.getClass().getField(fieldName).get(this);

        } catch (NoSuchFieldException ex) {
            Logger.getLogger(BaseRequest.class.getName()).log(Level.SEVERE, null, ex);
        } catch (SecurityException ex) {
            Logger.getLogger(BaseRequest.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IllegalArgumentException ex) {
            Logger.getLogger(BaseRequest.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            Logger.getLogger(BaseRequest.class.getName()).log(Level.SEVERE, null, ex);
        }

        return null;
    }
}
public class CredentialsPOJO extends BasePOJO{
    public String username;
    public String password;
}
credentialsPojo.getField("username");
String name = pojo.getProperty("name");
Integer age = pojo.getProperty("age");
我很快就创造了这个,这很可怕,但它很有效。但我想把它改成更合适的模型来模拟那个物体

También he creado el-siguiente:

public class BasePOJO{

    private Map<String, Object> parameters = new HashMap<>();


    public void addParameter(String paramName, Object value){
        parameters.put(paramName, value);
    }

    public Object getParameter(String paramName){
        return parameters.get(paramName);
    }
}
公共类BasePOJO{
私有映射参数=new HashMap();
public void addParameter(字符串参数名、对象值){
parameters.put(paramName,value);
}
公共对象getParameter(字符串paramName){
返回参数.get(paramName);
}
}
我更喜欢这个对象,它的OO解决方案,问题是它只返回一种对象类型

其思想是,使用此POJO的对象可以以通用方式访问其属性。
如果有一个设计模式能更好地解决这个问题,那么我可以实现它。

您即将创建一个新的设计模式。这通常是个坏消息

使用通用POJO,在调用方法时无法从IDE获得支持(因为它们根本不存在)。此外,如果您忘记了字段或拼写错误,您也会遇到问题。若不冒字符串中的名称出现问题的风险,重构也是不可能的

如果项目中不止您一人,您的同事是否能够理解并使用此解决方案?你能在6个月后、1年后、5年后再回来吗

尽可能简单地使用属性方法(getXyz、setXyz),并根据其用途对具有不同类的对象调用它们

查看您的IDE,它可能能够为您的字段自动生成getter和setter方法,因此本质上,您只需设置字段,然后按下按钮即可完成其余操作。(IntelliJ IDEA和Eclipse也做了这件事,我知道有两个。我很确定Netbeans也做了。)

如果你不确定你需要什么课程,那就为你的问题创建课程。一个好的开始是为用例文本中的名词创建类,为动词创建方法。之后,你就可以开始推广了。(尽管要小心API、框架和适合所有人的解决方案,即使它们很诱人……我也喜欢它们!直到我意识到我正在构建一个静态站点生成器,而不是打印一些HTML文件……通常是几周后……)

说到这里,可能有一些框架可以从数据库模式(Hibernate?)和web服务等生成类,也许这就是方法。无论如何,这些仍然是具有实际属性方法等的类


希望这有帮助

类似的东西在PHP中工作(例如Magento-magic方法),我真的认为这是一种糟糕的机制

为什么?

如果字段不存在,则没有IDE控件。您的类API不清楚,因此出错的风险非常高。您必须研究实现,以了解可以使用哪些字段。在您的示例中,您还通过公开字段来打破封装,这样任何人都可以直接使用它,而无需使用您的方法


在这些日子里,使用自动生成的getter/setter没有必要这样做。如果您想摆脱样板文件的getter/setter代码,可以使用例如。

术语澄清

POJO=普通的旧Java对象,也就是说,它不使用一些用于“修饰”对象行为的第三方注释(Hibernate的实体注释,或者已经提到的生成方法的Lombok)。与您的案例相匹配的是Bean=类,每个类字段都有getter和setter

问题的解决方案

// derive type from left side of the assignement operator
public <T> T getProperty(String paramName){
    return (T) parameters.get(paramName);
}
退税

由于给定的方法只是显式地将映射值强制转换为“赋值运算符左侧的任何类型”,因此无法实现编译时检查,从而在写入后立即发出警告:
Integer age=getProperty(“name”)。注意,在执行代码时,还存在运行时类型检查。这样的赋值将抛出一个
ClassCastException

请记住,只要您将map定义为
map
,就无法获得编译时检查-给定键下的值实际上可以是任何值。这也适用于反射方法,因为
getField(String)
返回隐藏在
Object
类型中的属性值

要进行编译时检查,请阅读建议部分

建议

我强烈建议您使用project,正如@Peteef已经提到的。确保在IDE中也安装了lombok插件,否则自动生成的方法将生成语法错误

注释将为每个字段生成getter,为每个非最终字段生成setter。此外,
@Data
注释还将生成
equals
hashCode
方法,当对象存储在或集合中时,这些方法非常重要。如果要检查两个对象是否相同(相同的字段值),方法
equals
可能也是可取的

注意,如果这些类被用作简单的数据保持器,那么您仍然可以使用带有公共字段的简单类,而不使用getter/setter。当然,这不是OOP,但你不必盲目地遵循每一个惯例(有时它们是有效率的)


在没有实际收益的情况下,为什么要进行推广?你需要实现什么?我需要概括它,因为那个对象必须经过几个过程