我发现自己处于一种我想要使用界面的情况,但我是第二次猜测自己。
我正在编写一份处理保险申请的申请。有一个Application对象包含有关保险应用程序的所有数据。这包括有关被保险人,拥有保险单的实体以及将支付保险费的实体的数据。
我使用术语实体,因为该政策可由个人或信托拥有(或支付)。我知道我在与业主或付款人打交道时,但我不一定知道该所有人或付款人是个人还是信托。我最初创建了Owner接口,以减少基于强制转换和基于实例的逻辑。我计划在Payor界面上做主食,但我现在正在猜测自己。
这可能就是你现在需要知道的全部内容。这是一些代码:
public class Application{
private Person insured;
private Owner owner;
private Payor payor;
...
}
public interface Owner{
public void setAddress(Address address);
public Address getAddress();
public void setId(String id);
public String getId();
public void setPIN(String pin);
public String getPIN();
}
public interface Payor{
public void setAccount(Account account);
public Account getAccount();
}
public class Person implements Owner, Payor{
...
}
public class Trust implements Owner, Payor{
...
}
我是在正确的道路上还是应该以不同的方式做到这一点?让我暂停的事实是,不是每个人都是业主或付款人。
当我更多地考虑时,我觉得所有者和付款人不像“分类”那样“行为”。这会使我在这里使用接口不正确吗?如果是这样,您对替代解决方案有什么建议吗?最好能让我继续透明地使用人和信托作为业主和付款人吗?
我担心的部分原因来自于不太熟悉的开发人员,如下所示让一个人混淆了一个人。
Application app = new Application();
Person timmy = new Person();
Owner smithFamilyTrust = new Trust();
Payor steve = new Person();
app.setInsured(timmy);
app.setOwner(smithFamilyTrust);
app.setPayor(steve);
...
//this would run, but would be wrong
if(timmy instanceof Owner){
//Do Owner Stuff.
}
//this would run, and be correct
Owner owner = app.getOwner();
//Do Owner Stuff
修改以澄清“所有者资料”
此时,“所有者的东西”很简单。获取/设置所有者的ID,PIN或地址:
//I want this
app.getOwner().getId();
app.getOwner().getPIN();
app.getOwner().getAddress();
//I don't want this
if(app.getOwner() instanceof Person){
Person owner = app.getOwner();
owner.getId();
owner.getPIN();
owner.getAddress();
} else if(app.getOwner() instanceof Trust){
Trust owner = app.getOwner();
owner.getId();
owner.getPIN();
owner.getAddress();
}
最初我认为我应该使用某种Entity超类,让Person和Trust扩展该类,但它们以不同方式存储和检索ID和PIN。相同行为的不同实现使我得到了接口。
我仍然可以使用Entity超类,但我觉得我无法准确地表示该Entity类的“通用”ID或PIN。我必须实现Person的ID和PIN逻辑或Trust的ID和PIN逻辑,然后在其他类中覆盖它。这对我来说是错的。我想Entity可能是Person和Trust扩展的抽象类,但我不确定它比使用接口更好。
答案 0 :(得分:3)
以这种方式使用接口可能适合也可能不合适。如果你是第二次猜测自己,那么你可能过早地介绍它们。
接口的实际目的是允许一段代码针对多个实现运行,例如
interface Contactable
Address getAddress()
end
class Person implements Contactable
Address getAddress(){
...
}
end
class Company implements Contactable
Address getAddress() {
...
}
end
class RenewalReminderJob extends CronJob {
public void perform() {
for(Contactable upForRenewal : listOfCompaniesAndPeople) {
remind(upForRenewal)
}
}
}
通常最好从具体类开始,然后在发现要对包含相同信息的不同类执行操作时引入接口(使用重构)。在上面的例子中,它将是地址。
在您的代码库开发过程中主动搜索接口的过程非常强大,它可以让您发现可能不会立即显现的概念。
答案 1 :(得分:1)
实现这一点的正确方法就是这样 应用程序具有“'角色'实体”(即实体在应用程序中扮演不同的角色)
实体可以是个人/组织/受托人等
因此,如果您以这种方式构建类,则不会出现问题。
作为一个例子,我可以使用
进行申请 entity1 (insured ) - person
entity2 (payer ) - person
entity3 (beneficiary) - trustee
entity4 (broker) - organisation
答案 2 :(得分:0)
你回答了自己的问题
我是在正确的道路上还是应该 这样做会有所不同吗?事情 那让我停下来的是事实 不是每个人都是业主 或付款人。
我想的更多,我觉得 所有者和付款人不是“行为” 就像“分类”一样。那样做 在这里使用接口 不正确的?
接口用于定义行为。
您是否尝试过子类方法?
答案 3 :(得分:0)
“所有者和付款人的行为不是分类。”
是否有与之相关的行为?例如,您可能需要一个方法
sendInvoice(Payor payor)
或
Payor getAddressForInvoice()
如果是这样,那么你可能需要这些接口,特别是如果他们可能是个人或公司。
答案 4 :(得分:0)
您可以做的一件事是从继承切换到遏制。您可以说,“人或信托可以包含所有者或付款人”,而不是说“人或信托可以是所有者或付款人”:
public class Person {
public Owner getOwner() { /* will return null if this person is not an Owner */ }
public Payor getPayor() { /* will return null if this person is not an Payor */ }
}
public class Trust {
public Owner getOwner() { /* will return null if this trust is not an Owner */ }
public Payor getPayor() { /* will return null if this trust is not an Payor */ }
}
我不确定这是否是正确的答案,因为我不确定“所有者”和“付款人”分类背后的业务逻辑。如果某人是所有者,这是否意味着他可以拥有任何申请?或者,这只是意味着这个特定的人拥有这个特定的应用程序?如果后者为真,那么您可以从公共基接口(例如“LegalEntity”)扩展Person和Trust,并使用Visitor pattern而不是instanceof检查来提供特定于子类的行为。
答案 5 :(得分:0)
您的界面没有问题。 Owner
界面只是意味着能够拥有东西,除非你想对穷人Timmy
非常不公平,否则我看不出他应该被排除在拥有之外的原因。
关于您的担忧,我认为您有点过度保护:您的系统中任何时候都会有多个Owner
个实例,我看不到任何潜在的开发人员认为他们可以选择任何一个并将其视为特定应用程序的所有者。