2
//Interface DAO

    public abstract class BaseDAO<T extends BaseDTO> {


    public void update(T t) throws DBException {
     Field[] fieldsToInsert = t.getClass().getDeclaredFields();
    //code to update database object academic or event
    }

     public Integer create(T t) throws DBException {
      Field[] fieldsToInsert = t.getClass().getDeclaredFields();
    //code to create academic or event in database
    }

} 



//Concrete DAOs
public class AcademicDAO extends BaseDAO<AcademicDTO> {
//provide implementation
}

public class EventDAO extends BaseDAO<EventDTO> {
//provide implementation
}



//Transfer object
public class AcademicDTO extends BaseDTO {
   String title;
   String surname;
   //getters and setters
}


public class BaseDTO {

    protected Integer ID;

    public Integer getID() {
        return ID;
    }

    public void setID(Integer ID) {
        this.ID = ID;
    }
}

大家好,我有一个示例代码,它遵循上述结构来创建一个小型 Java 应用程序来管理学术和活动。它宽大地遵循这种模式

1-你们专家比我更熟悉这种模式。我想了解为什么在这种情况下使用泛型,以便 DAO 可以扩展和实现泛型基类。如果能用一个例子来说明泛型在这里的优势是多么的好,那就太好了。

2 - 我也见证了java Fields的使用。泛型和字段之间有联系吗?

我想在学术报告中记录 DAO 模式,但我发现很难理解泛型反射场如何在这里发挥作用。它们是否支持灵活性和松散耦合?

4

2 回答 2

1

您提供的代码是一组可重用的加载和持久化实体的逻辑。很多时候,在一个非平凡大小的应用程序中,您最终会持久化许多不同类型的对象。在此示例中,您可以根据需要定义任意数量的对象,但只定义实际保存和加载一次的逻辑。通过询问 DTOField那里有哪些对象,它可以获取数据以帮助构建用于加载和保存的查询。

泛型允许您在保持类型安全的同时使用此模式。 AcademicDAO只能处理AcadmeicDTO。你不能AcademicDAO用来存储EventDTOField泛型允许类的实例在处理对象时依赖更具体的类型。如果您没有泛型,BaseDAO则将采用Object,并且您将无法访问除 Object 提供的方法之外的任何方法,因为 JVM 不知道提供了什么类,因此它必须将其知识限制为Object. 使用getClass().getDeclaredFields()绕过该限制,因为getClass()返回参数的实际类Object

Field只是一种使用反射来访问每个 DTO 中的属性值的方法。如果您必须使用 直接访问字段,则getTitle()无法重用通用基类来进行持久化。当您需要访问 EventDTO 时会发生什么?您必须为此提供逻辑。 Field允许您跳过该逻辑。

编辑:

为了解释我所说的访问的意思getID,您可以在其中执行以下操作,BaseDAO因为T已知a 定义BaseDTO了一个getID()方法:

public abstract class BaseDAO<T extends BaseDTO> {

    public boolean update(T t) throws DBException {
        Integer id = t.getID();
        Field[] fields = t.getClass().getDeclaredFields();
        // Assuming you have a db object to execute queries using bind variables:
        boolean success = db.execute("UPDATE table SET ... WHERE id = ?", id.intValue());
        return success;
    }
}

如果你有这个(在非泛型类中):

public boolean update(Object o) throws DBException {
    // This line doesn't work, since Object doesn't have a getID() method.
    Integer id = t.getID();
    Field[] fields = o.getClass().getDeclaredFields();

    boolean success = db.execute("UPDATE table SET ... WHERE id = ?", id.intValue());
    return success;
}

您必须查看这些Field对象,或者询问 ID 字段并假设它存在。

于 2013-04-06T00:39:45.393 回答
1

对于问题 1。无论 DTO 的类型如何,泛型的使用都允许使用update和使用相同的实现。create考虑一下你是否没有使用泛型。那么你可以为参数类型做的最好的事情update就是BaseDTO,但是你可以调用

academicDAO.update( eventDTO )

这是没有意义的。使用您拥有的代码,这将是一个类型错误。所以主要优点是:更好的类型检查。

对于问题 2。 Fields 的使用允许单个实现updatecreate处理各种具体类型的 DTO 对象。

于 2013-04-06T00:40:02.053 回答