Должен ли я использовать такие интерфейсы? - PullRequest
4 голосов
/ 30 ноября 2010

Я нахожусь в ситуации, когда я хочу использовать интерфейсы, но я сам догадываюсь.

Я пишу приложение для обработки страховых заявок. Существует объект Application, в котором хранятся все данные о приложении страхования. Сюда входят данные о застрахованном лице, субъекте, которому будет принадлежать страховой полис, и субъекте, который оплатит страховое покрытие.

Я использую термин сущность, потому что полис может принадлежать (или оплачиваться) Лицом или Трастом. Я знаю, когда имею дело с владельцем или плательщиком, но я не обязательно знаю, является ли этот владелец или плательщик лицом или трастом. Первоначально я создал интерфейс Owner для сокращения приведения и логики на основе instanceof. Я планировал сшить на интерфейсе 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

Редактировать, чтобы уточнить "Owner Stuff"

На данный момент «вещи владельца» просты. Такие вещи, как получение / установка идентификатора владельца, 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 расширили этот класс, но они по-разному хранят и получают идентификаторы и PIN-коды. Различная реализация одного и того же поведения привела меня к интерфейсам.

Я все еще мог бы пойти с суперклассом Entity, но я чувствую, что не могу точно представить «универсальный» идентификатор или ПИН-код для этого класса Entity. Мне нужно будет реализовать логику идентификатора и PIN-кода Person или логику ID и PIN-кода Trust, а затем переопределить ее в другом классе. Это неправильно для меня. Я полагаю, что Entity может быть абстрактным классом, который расширяют Person и Trust, но я не уверен, что это лучше, чем использование интерфейса.

Ответы [ 6 ]

3 голосов
/ 01 декабря 2010

Использование интерфейсов таким способом может или не может быть целесообразным. Если вы уже догадались, значит, вы представили их слишком рано.

Практическая цель интерфейсов состоит в том, чтобы позволить куску кода работать с несколькими реализациями, например

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 голос
/ 03 октября 2012

Правильный способ реализации этого так в приложении есть «сущности« роли »(т. е. сущности играют разные роли в приложении)

Субъектом может быть лицо / организация / попечитель и т. Д.

Так что если вы структурируете свои классы таким образом, у вас не будет проблем.

В качестве примера я могу использовать приложение с

             entity1 (insured )       - person 
             entity2 (payer )         - person 
             entity3 (beneficiary)    - trustee
             entity4 (broker)         - organisation
0 голосов
/ 01 декабря 2010

Нет ничего плохого в ваших интерфейсах.Интерфейс Owner означает только способность владеть вещами, и, если вы не хотите быть ужасно несправедливым по отношению к бедному Timmy, я не вижу причины, по которой ему следует запретить владение.

С уважениемк вашему беспокойству, я думаю, что вы немного чрезмерно защищены: в вашей системе будет одновременно несколько Owner экземпляров, и я не вижу ни одного потенциального разработчика, который предположил бы, что он может просто выбрать любой и рассматривать это каквладелец конкретного приложения.

0 голосов
/ 01 декабря 2010

Одна вещь, которую вы могли бы сделать, это перейти от наследования к содержанию.Вместо того, чтобы говорить «Лицо или траст может быть владельцем или плательщиком», вы бы сказали: «Лица и трасты могут содержать владельцев или плательщиков»:

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 */ }
}

Я не уверен, если этоправильный ответ или нет, однако, потому что я не уверен в бизнес-логике, лежащей в основе классификаций «Владелец» и «Плательщик».Если Лицо является Владельцем, означает ли это, что он может владеть любым Приложением?Или, напротив, это просто означает, что этот конкретный человек владеет этим конкретным приложением?Если последнее имеет значение true, тогда вы можете расширить и Person, и Trust из общего базового интерфейса (например, «LegalEntity») и использовать шаблон Visitor вместо instanceof проверок для обеспечения поведения, специфичного для подкласса.,

0 голосов
/ 01 декабря 2010

«Владелец и Payor - это не столько поведение, сколько классификация».

Есть ли поведение, связанное с ними?Например, вам может понадобиться метод

sendInvoice(Payor payor)

или

Payor getAddressForInvoice()

Если это так, то вам, вероятно, понадобятся интерфейсы, особенно если это могут быть люди или корпорации.

0 голосов
/ 30 ноября 2010

вы ответили на свой вопрос

Я на правильном пути или я должен делать это по-другому? Вещь это дает мне паузу является фактом что не каждый человек будет владельцем или плательщик.

Когда я думаю об этом больше, я чувствую, что Владелец и Payor не "поведение", поэтому так же, как "классификации". Это делает использовать мои интерфейсы здесь неправильно?

Интерфейсы для определения поведения.

Вы пробовали подход подкласса?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...