2015-04-24 31 views
4

我是新来的Java和我编码像这样由一个模块化的应用程序:如何处理模块化应用程序中的泛型类/接口?

*************   *******   *********** 
*   *   *  *   * Data * 
* Front-end * -------- * API * ------- * Handler * 
*   *   *  *   *   * 
*************   *******   *********** 

从本质上讲,我希望能够定义具有N类的API,然后有一个“数据处理程序”模块处理将对象存储在某个地方(例如数据库),而前端不需要知道如何实现的任何内容。

因此,假设我在API中定义了两个类:Contract和Company。 我希望前端可以这样做:

myContract = new Contract(); 
myCompany = new Company(); 
myContract.setCompany(myCompany); 
myContract.save(); 
myCompany.save(); 

这样,将来我可以改变我存储的数据(数据处理程序模块)的方式,在不改变任何代码前端。

为此,我在API模块中为Contract和Company编写了两个接口。 然后,在数据处理程序模块中,我写入了实现两个接口的类:DbContract和DbCompany。现在

,我遇到的问题,因为我已经定义在合同接口的getter/setter方法为:

public interface Contract { 
    public Company getCompany(); 
    public void setCompany(Company company); 
} 

而且在DbContract实现他们为:

public class DbContract implements Contract { 
    private DbCompany company; 

    @Override 
    public Company getCompany() { 
     return this.company; 
    } 

    @Override 
    public void setCompany(Company company) { 
     this.company = company; 
    } 
} 

然而,我我得到类型不匹配错误遍布各地... 我完全错过了观点?我应该怎么做呢?

在此先感谢您的帮助。

+1

在'setCompany',你不能没有做类型转换分配'Company'到'DBCompany'参考。您何时/如何创建'DBCompany'? – BretC

+0

我的想法是在名为Manager的API中有一个类,该类具有实例化和返回对象的方法。像'公共合同createContract(){返回新的DbContract(); ''。是否有正确的方法去解决这个问题? –

+1

你的API的主要目的是隐藏实现细节,使得'Frontend'只与接口一起操作。通过在那里创建对象,你打破了这个规则。 –

回答

1
myContract = new Contract(); 

这不起作用,因为您无法创建接口的实例。

你似乎有正确的想法,但似乎对“实施”一词有一种误解。

如果前端需要创建这些接口的实例,则需要知道实现或提供它自己的实现。另一方面,如果前端不应该知道实现,它应该调用后端来创建一个新实例。

除此之外,制作ContractCompany数据容器并移动保存到服务的实际逻辑可能是更好的设计,例如,你的代码应该是这样的:

class Contract { ... } //as before, but classes not interfaces 
class Company { ... } //as before, but classes not interfaces 

创建一个新的合同:

Contract myContract = new Contract(); 
Company myCompany = new Company(); 
myContract.setCompany(myCompany); 

contractService.save(myContract); //assuming this would save the company as well 

你可以查找服务或让它被注入。对于后者,请看Spring依赖注入。

更新:

在你的评论指出CompanyContract将JPA实体,如果我理解正确你不想前端有正在使用JPA任何概念。

在这种情况下,你有两个选择:

  1. 使对象纯POJO和添加XML在后端的JPA映射。然后你会将从前端传递来的每个实例都视为分离的实体。

  2. 如果您想为映射使用注释,并且不希望前端知道您需要提供API使用的中间层(称为数据传输对象= DTO)。在内部,后端将在实体和DTO之间进行转换。

+0

谢谢你的回复。这种方法的问题是我想使用JPA和EclipseLink来存储数据,所以每个类都需要被定义为一个实体。如果我使用这种方法,那么前端将不再是“存储不可知论”。 –

+1

@NiccolòZapponi取决于。如果前端可能知道JPA,它就不需要知道正确的实现(它可能是Eclipse Link或Hibernate)。尽管我会扩大我的答案。 – Thomas

+0

谢谢,我真的很感激! –

2

变化

private DbCompany company; 

private Company company; 

而且每一件事应该是甜的。

否则,您将需要前端知道您正在处理和通用的公司类型。 这并没有被编译,但这样的:

public interface Contract<T extends Company>{ 
    public T getCompany(); 
    public void setCompany(T company); 
} 

public class DbContract implements Contract<DbCompany> { 
    private DbCompany company; 

    @Override 
    public DbCompany getCompany() { 
     return this.company; 
    } 

    @Override 
    public void setCompany(DbCompany company) { 
     this.company = company; 
    } 
} 
+0

感谢您的回复。第一种方法是我最初遵循的,但是我使用JPA和EclipseLink将对象存储在数据库中,所以我需要类型是正确的(因为它们被定义为实体)。 –

+0

您需要关注一下您的体系结构,因为我会同意@Thomas的说法,前端应该最好不知道它使用的是什么类型的对象。如果您的数据处理程序使用创建NewCompany和createNewContract的方法进行了增强,则第一个选项可用。 – redge