В самам конце приведен код, есть вопрос, но туда добавить не смог, прошу не пинать ногами.
Сам столкнулся с подобной задачей, прошу помощи...
Код привожу чужой:
От: Other Sam
Дата: 03.09.10 12:44
Оценка: 7 (1) +1
...
SD>Определить иерархию цветов. Создать несколько объектов-цветов. Собрать букет с определением его стоимости.
... поскипано ...
В такой постановке задача не имеет сколько нибудь обоснованного решения.
Вот примерное решение с разъяснением на какие грабли наступаем, и какие обходим.
// 1. Я решил запихать все что можно в абстрактный базовый класс
// чтобы код конкретных цветочков был как можно короче.
// 2. Хотя нет абстрактных методов, все равно класс помечен как абстрактный,
// чтобы никто не подумал добавлять неконкретный цветочек в букет.public abstract class Flower {
private final String name;
private final BigDecimal price; // Деньги это не вещественные цисла. Поэтому для их подсчета
// нужно всегда использовать какой-то целочисленный тип.protected Flower(String name, BigDecimal price) {
this.name = name;
this.price = price;
}
// 3. Общие методы для всех цветочков перенесены сюда.
// (чтобы не дублировать в каждом цветочке)public String getName() {
return name;
}
// 4. А вот этот метод относится не к цветочку, а к товару!!!
// Здесь у нас произошло смешивание понятий. Цена это атрибут товара
// а не растения!!! Но поскольку смешались оставим пока так.public BigDecimal getPrice() {
return price;
}
}
public class Rose extends Flower {
// 5. собственно конкретный класс цветовpublic Rose() {
super("Rose", BigDecimal.valueOf(5.22).setScale(2, RoundingMode.HALF_EVEN));
}
}
public class Tulip extends Flower {
public Tulip() {
// Реально при работе с деньгами я видел две стратегии.
// Использовать рубли/копейки (т.е. 2 знака после запятой)
// или использовать 4 цифры после запятой.
// Здесь я использую 2 цифры после запятой.
// Кстати это является потенциально опасным местом
// В коде закодированно вещественное число 1.27, которое затем округляется
// до целочисленного 1.27
// По идее точнее было-бы
// BigDecimal.valueOf(127).divide(BigDecimal.valueOf(100), RoundingMode.HALF_EVEN)
// .setScale(2, RoundingMode.HALF_EVEN)
// Но такой код очень сложно читать. Так что я через float задал.
super("Tulip", BigDecimal.valueOf(1.27).setScale(2, RoundingMode.HALF_EVEN));
}
}
// 6. Собственно класс букетика.
// Поскольку нужно "собрать" букет и посчитать его цену
// появляются две обязанности "собрать букет" "посчитать цену"
// Эти обязанности нельзя возлагать на классы цветочков. (Это определяется анализом)
// Следовательно новый класс для "собрать букет".
// Собирание букета сильно похоже на использование коллекций - поэтому
// будем пользоваться уже готовой коллекцией.
// Но чтобы в готовую коллекцию добавить еще одну ответственность -
// "посчет стоимости".
// Так и сделаем - добавим метод.public class FlowerPack extends ArrayList<Flower> {
public BigDecimal getPackPrice() {
BigDecimal summ = BigDecimal.ZERO;
for (Flower f : this) {
summ = summ.add(f.getPrice());
}
return summ;
}
}
public void testBuket() {
FlowerPack pack = new FlowerPack();
pack.add(new Rose());
pack.add(new Rose());
pack.add(new Tulip());
System.out.println(pack.getPackPrice());
}
возникает интересный вопрос...
Что будет с нашим букетом. если там 20 одинаковых роз...
Разве целесообразно будет в лист напихивать 20 объектов? Есть мысль напихивать объекты цветов, чтобы добавлялся не сам объект, а попутно с количеством. Но само количество по моему не должно быть атрибутом объекта цветка....
Прошу подсказать идею по букету
Здравствуйте, sobakam, Вы писали:
S>Что будет с нашим букетом. если там 20 одинаковых роз...
Что будет?
S>Разве целесообразно будет в лист напихивать 20 объектов?
Зависит от решаемой задачи. Если накладную заполнять для оптового магазина, то, наверное не имеет.
А если каждую розу наделить уникальным значением атрибутов, то почему нет. Но мысль верная.
S>Есть мысль напихивать объекты цветов, чтобы добавлялся не сам объект, а попутно с количеством. Но само количество по моему не должно быть атрибутом объекта цветка....
Если клиенту не нужно различать отдельные цветки, то да. А если это модель какой-нибудь выставки, где каждый лепесток на учете. То нет.
S>Прошу подсказать идею по букету
Это просто разминка по ООП. Когда будет конкретная цель, тогда будут конкретные решения. Но направление мысли у вас верное.
Здравствуйте, Blazkowicz, Вы писали:
B>Здравствуйте, sobakam, Вы писали:
S>>Что будет с нашим букетом. если там 20 одинаковых роз... B>Что будет?
S>>Разве целесообразно будет в лист напихивать 20 объектов? B>Зависит от решаемой задачи. Если накладную заполнять для оптового магазина, то, наверное не имеет. B>А если каждую розу наделить уникальным значением атрибутов, то почему нет. Но мысль верная.
S>>Есть мысль напихивать объекты цветов, чтобы добавлялся не сам объект, а попутно с количеством. Но само количество по моему не должно быть атрибутом объекта цветка.... B>Если клиенту не нужно различать отдельные цветки, то да. А если это модель какой-нибудь выставки, где каждый лепесток на учете. То нет.
S>>Прошу подсказать идею по букету B>Это просто разминка по ООП. Когда будет конкретная цель, тогда будут конкретные решения. Но направление мысли у вас верное.
Конечно, есть моменты, но, в любом случае, букет навряд ли будет состоять из всех оригинальных цветов Думаю найти подходящий способ хранения... Хочется просто так сделать, чтобы самому понравилось... Вообще такая задача применима к хранению объектов вообще, даже не в букете собственно дело, просто я , как начинающий изучение Java, наткнулся на тот букет и задался вопросом, как бы сделал я.
Здравствуйте, sobakam, Вы писали:
S>Конечно, есть моменты, но, в любом случае, букет навряд ли будет состоять из всех оригинальных цветов
Букет вряд ли состоит из всех полностью идентичных цветков.
S>Думаю найти подходящий способ хранения...
Это не "хранение". Это дизайн модели предметной области. И моделью оно называется, потому что задача не создать модель ради модели, а создать модель ради конретного решения. У продавца модель одна, у флориста — другая, у ботаника — третья. Хотя все оперируют одними и теми же цветами.
S>Хочется просто так сделать, чтобы самому понравилось...
Решайте все же конкретную проблему. Хотя если самому понравиться, то, конечно, мотивация будет выше.
S>Вообще такая задача применима к хранению объектов вообще, даже не в букете собственно дело, просто я , как начинающий изучение Java, наткнулся на тот букет и задался вопросом, как бы сделал я.
Гуглите про "моделирование предметной области". Разные модели решают разные задачи. Если вы создадите какую-нибудь модель, то к ней всегда найдется задача, в которой эта модель будет плохо работать.
Я хочу ограничиться конечно в рамках данной узкой задачи.
Атрибутов в классах будет не много, в принципе те что есть достаточны.
По большому счету роза, тюльпан, орхидея. На базе розы могу создать обьект чайная роза итд...
Я представил, допустим, таблицу в свинге. По большому счету так или иначе предоставить данные необходимо в наглядном виде. А подсчет количества одинаковых объектов-это, как ни крути, еще метод и дополнительные вычисления...
Я это дело просто уже набросал, буду искать подходящий вариант конструкции.
Вас спасибо за участие
Здравствуйте, sobakam, Вы писали:
S>Я хочу ограничиться конечно в рамках данной узкой задачи. S>Атрибутов в классах будет не много, в принципе те что есть достаточны. S>По большому счету роза, тюльпан, орхидея. На базе розы могу создать обьект чайная роза итд... S>Я представил, допустим, таблицу в свинге. По большому счету так или иначе предоставить данные необходимо в наглядном виде. А подсчет количества одинаковых объектов-это, как ни крути, еще метод и дополнительные вычисления... S>Я это дело просто уже набросал, буду искать подходящий вариант конструкции. S>Вас спасибо за участие
Тогда нужен не массив из Flower, а карта (map), который бы ставил в соответствие
Rose — 1 000 000 штук
Tulip — 1 001 штука
Или как-то так. Тут верный вопрос ещё задали — а что за требования в предметной области? Ведь можно дать ситуацию, что в букете 5 роз белых, 3 розы красных, 1 розовая... Т.е. тогда в карту неявно въезжает ещё и атрибут "цвет" — а в ходит ли он в атрибуты самого Flower? Ну и т.п.
Возможно, потребуется дополнительный класс (или даже иерархия) "валидатор букета": что на похороны надо чётное число цветов, на иные мероприятия — нечетное, для торжественных случаев нужен сложный букет не менее N видов цветов плюс аксессуары (корзинки, бабочки, беджики с пожеланиями etc), каждому цветку можно сопоставить дату его сбора, и тогда в букете не должно быть цветов старше, чем допуск для данного вида (одни сорта вянут быстро, другие нет).
...etc...
Re[6]: Пример странного ООП
От:
Аноним
Дата:
23.07.12 13:17
Оценка:
Здравствуйте, Mr.Delphist, Вы писали:
Благодарю за наводку, про map тоже счаз думал. Вообще по цвету, это будет атрибут конкретного объекта. То есть простая роза будет красная, чайная будет чайная, белая будет белая итд... Я так сделал чтобы особо не размахивать в иерархии. По сути название объекта будет отражать все свойства включая цвет. Набивать их буду скопом по очереди, как в том примере... Я задался именно вопросом чтобы не дублировать объекты, а хранить в классе букета их типа Объект-количество (одинаковых)... То есть при добавлении, скажем, в карту, проверять уникальность, ну и в случае нахождения такового в списке изменять количество. В противном случае-добавляем новый... Я правильно мыслю?
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, Mr.Delphist, Вы писали:
А>Благодарю за наводку, про map тоже счаз думал. Вообще по цвету, это будет атрибут конкретного объекта. То есть простая роза будет красная, чайная будет чайная, белая будет белая итд... Я так сделал чтобы особо не размахивать в иерархии. По сути название объекта будет отражать все свойства включая цвет. Набивать их буду скопом по очереди, как в том примере... Я задался именно вопросом чтобы не дублировать объекты, а хранить в классе букета их типа Объект-количество (одинаковых)... То есть при добавлении, скажем, в карту, проверять уникальность, ну и в случае нахождения такового в списке изменять количество. В противном случае-добавляем новый... Я правильно мыслю?
Абсолютно.
Re: Пример странного ООП
От:
Аноним
Дата:
25.07.12 07:31
Оценка:
Здравствуйте, sobakam, Вы писали:
S>Приветствую! S>Лазил по форуму, наткнулся на закрытую тему... S>http://www.rsdn.ru/forum/java/3945199.flat.2.aspx
S>возникает интересный вопрос... S>Что будет с нашим букетом. если там 20 одинаковых роз... S>Разве целесообразно будет в лист напихивать 20 объектов? Есть мысль напихивать объекты цветов, чтобы добавлялся не сам объект, а попутно с количеством. Но само количество по моему не должно быть атрибутом объекта цветка.... S>Прошу подсказать идею по букету
1. Вам надо понять, что меняется от цветка к цветку. Поведение или состояние.
2. Нужно понять, возможны ли изменения поведения или состояния в рантайме или все известно на этапе компиляции.
Если у вас меняется поведение, например различные цветки будут расти с различной скоростью, либо в разных направлениях, то выделяете интерфейс, типа:
public interface Flowable
{
void flow();
}
Теперь, надо определить как цветки имплментят ваш Flowable. Если поведение известно на этапе компиляции, то есть две опции — через наследование (не рекомендуется), через enum.
Скорее всего на этапе компиляции вы уже будете знать, какой цветок какую реализацию Flowable использует, значит, лучше реализовать цветок как enum, передав в констуркторе конкретную имплментацию Flowable. Если поведение нужно менять в runtime, добавляем сеттер.
Но поведение цветков скорее не меняется от цветка к цветку, у вас меняется цвет и, допустим, стоимость, т.е. состояние.
Цвет у цветков, допустим известен сразу, compile-time данные, а вот цена — хотелось бы передать в runtime.
Если хоть одно из изменений состояния или поведение нужно менять в runtime, отказываемся от enum (оч. люблю их). Делаем сеттеры для состояний либо через конструкторы. Парметр один — цена, лучше через конструктор с типом BidDecimal price
Т.е. все ваши цветки будут наследовать какой то AbstractFlower и будут отличаться лишь двумя состоянями:
1. цвет, его задаем через private static final String COLOR = "red"; — величина для класса всегда будет постоянная.
2. цена, передаем всегда в конструкторе
Опять же, вы можете рассмотреть каждый цветок — как результат аггрегации лепестков, корня, бутона и т.д. Это уже другая история, но направление, надеюсь, вам понятно
Хотелось бы услышать аргументированную критику.
...
S>возникает интересный вопрос... S>Что будет с нашим букетом. если там 20 одинаковых роз... S>Разве целесообразно будет в лист напихивать 20 объектов? Есть мысль напихивать объекты цветов, чтобы добавлялся не сам объект, а попутно с количеством. Но само количество по моему не должно быть атрибутом объекта цветка.... S>Прошу подсказать идею по букету
А какую задачу вы решаете? Для задачи "есть букет, нужно на странице отобразить его стоимость" достаточно вот такого мега-дизайна:
class BunchOfFlowers {
public int totalPrice; // количество денег в копейках, например
}
BunchOfFlowers bunch = new BunchOfFlowers();
bunch.totalPrice = 100000; // 1000 рублей
Если у вас всё чуть детальнее и можно сконструировать букет по количествам цветов, то:
class Flower { // цветок имеет имя и стоимость (Роза, 150 рублей)public String name;
public int price;
}
class BunchLine { // order line -> bunch line (лучше не придумалось)public Flower flower;
public int numberOfItems;
}
class BunchOfFlowers { // букет состоит из нескольких наборов цветов, в каждом из которых цветы одинаковыеpublic Collection<FlowerLine> flowerLines;
}
// это не цветок в смысле "вот этот конкретный цветок", а в смысле "вид цветка"
Flower rose = new Flower("Rose", 15000); // розы по стописят у нас
Flower tulip = new Flower("Tulip", 10000); // тюльпаны по сотне отдам
BunchLine roses = new BunchLine(rose, 13); // 13 розочек
BunchLine tulips = new BunchLine(tulip, 11); // 11 тюльпанчегов
BunchOfFlowers bunch = new BunchOfFlowers(Arrays.toList(toses, tulips));
Если ваш конструктор букетов настолько крут, что можно ещё и положение отдельных цветов в букете определять, будет что-то вроде:
class Flower {...} // Роза, 150 рублейclass PositionedFlower {
public Flower flower; // Роза, 150 рублейpublic FlowerPosition position; // Посерединке
}
class BunchOfFlowers {
public Collection<PositionedFlower> positionedFlowers;
}
Flower rose = new Flower("Rose", 15000);
Flower tulip = new Flower("Tulip", 10000);
BunchOfFlowers bunch = new BunchOfFlowers(Arrays.toList(
new PositionedFlower(rose, FlowerPosition.Center),
new PositionedFlower(rose, FlowerPosition.Left),
new PositionedFlower(rose, FlowerPosition.Right)
));
В любом случае я не представляю ситуацию когда вам может понадобиться иерархия вроде Tulip implements Flower — это имеет смысл только в академических задачках и по глупости сравнимо с обсуждением наследования квадрата от прямоугольника.
Объект — та хрень, которой предполагается дать инкапсуляцию,
наследование или полиморфизм. Если ничего из этого не надо, то и не
делайте объекта.
В данном случае, цветок — объект и представляет разные свойства: цена,
цвет, повод к которому подходит и т.п. Но при этом цветок не является
ТОВАРОМ! Цветок, как объект, не должен знать что он товар!!!
С точки зрения продавца товар — это товар. Имеющий вид и количество.
Примерно так:
class Сommodity{
private Class clazz;
private int quantity;
...
public Сommodity(class c){this.clazz=c;}
...
}
Соответсвено твой букет для продавца
Сommodity bunch = new Commodity(Rose.class);
bunch.setPrice...
bunch.setRebate...
bunch.setQuantity...
Конечно могут быть и другие варианты, но решение в плане ШАБЛОНА
однозначно — букеты и прочие счастья должны ВКЛЮЧАТЬ в себя объект
класса, без необходимости разбираться в деталях объекта если сие не
требуется.
ЗЫ. Тут правильно заметили: сначала моделируем реальность, а потом уже
кодим. Иначе непонятки логические зароются в код и скушают туеву хучу
времени. На реальной работе, когда узнают источник проблемы — будут бить
ногами, прямо на митинге.
Народ, всем огромное спасибо по советам.
Вообще задача стояла Определить иерархию цветов. Создать несколько объектов-цветов. Собрать букет с определением его стоимости...
То есть как ни крути иерархия должна быть...
Был сделан абстрактный класс, как из примера
public abstract class Flower {
private final String name; //Flower Nameprivate final String color; //Flower colorprivate final BigDecimal price; //Price of a single flower
//Constructor with parametersprotected Flower(String name,String color, BigDecimal price) {
if ( price.signum() < 0) {
throw new IllegalArgumentException("Price can not be less then zero.");
}
if (name == null) {
throw new NullPointerException("Argument name can not be null.");
}
if (name.isEmpty()) {
throw new IllegalArgumentException("Name of flower can not be empty.");
}
if (color == null) {
throw new NullPointerException("Argument color can not be null.");
}
this.name = name; //Set a Flower Namethis.color = color; //Set a Flower colorthis.price = price; //Set the Price for one flower
}
public String getName() {
return name;
}
public String getColor() {
return color;
}
public BigDecimal getPrice() {
return price;
}
}
public class BouquetStore {
public static void main(String[] args) {
//Creates а new instance of the class Rose, object Tea Rose
Flower TeaRose = new Rose("TeaRose","Tea", BigDecimal.valueOf(7.23).setScale(2, RoundingMode.HALF_EVEN));
//Creates а new instance of the class Bouquet, object pack. This name is "Happy New Year"
Bouquet pack = new Bouquet ("Happy New Year");
pack.put(new Rose(),1);
pack.put(TeaRose,2);
pack.put(new Orchid(),2);
pack.put(new Tulip(),1);
pack.getPackPrice();
//Create а new Bouquet "Wedding"
Bouquet pack1 = new Bouquet("Wedding");
pack1.put(new Rose(),5);
pack1.put(new Orchid(),2);
pack1.put(new Tulip(),1);
pack1.getPackPrice();
//Create а new Bouquet "Love Story"
Bouquet pack2 = new Bouquet("Love Story");
pack2.put(new Rose(),15);
pack2.getPackPrice();
}
}
Еще подскажите убогому, не пинайте ногами, кроме всего прочего вот это:
public class Bouquet extends HashMap <Flower, Integer> {
protected String BouquetName;
То есть я имею в виду не будет ли это криво если я здесь добавляю поле BouquetName в класс при такой конструкции или
ИЛИ правильнее:
public class Bouquet
private Map <Flower, Integer> Pack = new HashMap <Flower, Integer>;
protected String BouquetName;
Приветствую любую критику!
Re[3]: Пример странного ООП
От:
Аноним
Дата:
06.08.12 05:59
Оценка:
правильнее S>
S>public class Bouquet
S> private Map <Flower, Integer> Pack = new HashMap <Flower, Integer>;
S> protected String BouquetName;
S>
+ не надо забывать про name conventions:
public class Bouquet
private Map <Flower, Integer> pack = new HashMap <Flower, Integer>;
protected String bouquetName;