ОО дизайн вопрос - PullRequest
       3

ОО дизайн вопрос

2 голосов
/ 17 июня 2011

У меня есть куча классов, таких как:

abstract class Product {
  BigDecimal price
  String name
}

class EdibleProduct extends Product {
  Date sellByDate
}

class FinancialProduct extends Product {
  Currency currency
}

В действительности существует более 2 подклассов, и каждый подкласс добавляет более одного свойства к родительскому. Я хотел бы использовать эти классы с API, например:

interface ProductDao {    

  Product create(Product product)
  Product update(Product product)
}

С наивной моделью, предложенной выше, нужно будет сделать что-то подобное в рамках реализации ProductDao методов

Product create(Product product) {
  // save the fields common to all Products

  if (product instanceof EdibleProduct) {
    // save fields specific to this implementation      

  } else if (product instanceof FinancialProduct) {
    // save fields specific to this implementation      
  }
}

Очевидно, приведение к типу реализации, как это отстой, поэтому я ищу способы создания, обновления и т. Д. Различных видов продуктов без ссылки на типы реализации (по крайней мере, в реализации ProductDao).

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

interface ProductType {}

class EdibleProductType {
  Date sellByDate
}

class FinancialProductType {
  Currency currency
}

затем добавление поля ProductType к Product. Я также подумал об использовании декоратора, но, похоже, это не избавит от необходимости опускать руки.

Языком реализации будет Java или Groovy.

Ответы [ 4 ]

2 голосов
/ 17 июня 2011

Если ProductDao.create просто копирует свой аргумент, добавьте новый метод в интерфейс Product, например

public Product createCopy();

и затем в каждом конкретном классе он будет знать, как сделать свою копию, например, с помощью конструктора копирования. Так что для EdibleProduct у вас может быть:

public Product createCopy() {
   return new EdibleProduct(this);
}

public EdibleProduct(EdibleProduct rhs) {
   // copy construct
}
2 голосов
/ 17 июня 2011

Если вы не можете использовать ответ Дейва (потому что было бы проблематично поместить код в сам продукт), вы можете захотеть взглянуть на Шаблон посетителя , который был разработан именно для этого типа проблемы.

0 голосов
/ 17 июня 2011

То, что вы хотите, это шаблон Chain of Reponsibilty.Имейте экземпляры каждого подтипа Product в Set и просто пройдитесь по Set и вызовите .create(final Product p); для каждого из них, они решат, является ли тип правильным, и сделают то, что им нужно.Это исключает неприятную конструкцию if/elseif и масштабируется до множества подклассов.

0 голосов
/ 17 июня 2011

Похоже, и я предполагаю, что версия Java / Groovy, которую вы используете, может сделать это, что вам нужен интерфейс, который вы можете преобразовать в любой из этих объектов.

Другими словами, есть IProduct и просто использовать его, используя динамический тип, который затем сможет во время выполнения действовать в зависимости от того, что он имеет с точки зрения свойств.

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