2015-11-12 4 views
5

Прежде чем задать вопрос, я должен сказать, что это домашнее задание, и я ищу идеи о том, как реализовать класс, который моделирует книгу.Класс Java, который моделирует книгу

В книге есть заголовок и много глав, каждая глава имеет заголовок и несколько подглавов. У каждого подраздела есть заголовок и список абзацев. Каждый абзац может содержать число и текст. Я хочу реализовать в ООП следующие функции: добавить/удалить: главы, подглавы и абзацы и отобразить книгу. У меня возникли проблемы с поиском правильной структуры для класса.

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

public class Element<T> { 
     int nr; 
     String Title; 
     ArrayList<T> x = new ArrayList<T>(); 

     Element() { 
      nr = 0; 
      Title = ""; 
     } 

     public void removeFromElement(int index) { 
      if (index <= 0 && index > x.size()) 
       System.out.println("The chapter doesn't exist"); 
      else { 
       x.remove(index); 
       System.out.println("Succesful deletion"); 
      } 
     } 

     public void addToElement(T elem) { 
      x.add(elem); 
     } 
    } 

    public class Paragraph { 
    int nr; 
    String text; 
    } 

    public class Subchapter extends Element<Paragraph> { 
    } 

    public class Chapter extends Element<Subchapter> { 
    } 

    public class Book extends Element<Chapter> { 
    } 
+3

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

+0

Какова будет ценность 'nr' в случае' Book'? – dsharew

+0

Ну, книга не должна иметь число, которое является одной из моих проблем. –

ответ

2

Ваша общая модель на самом деле имеет достаточный смысл. Вы идентифицировали повторяющийся код и отделили его от класса. Использование дженериков помогает сохранить чистоту. Стоит ли явно выделять слои дерева (так это то, что это по существу), так как Subchapters, Chapters и т. Д. Зависят от ваших точных требований.

Может быть проще просто определить узлы и листья дерева, но если вам нужно различное поведение на каждом уровне и не требуется гибкость для добавления или удаления большего количества слоев, тогда это нормально. Рассмотрим, например, если у вас когда-либо будет омнибус с Omnibus-> Book-> Chapter-> Subchapter-> Paragraph или книга с книгой-> Глава-> Раздел-> Подглав-> Параграф. Могла ли ваша модель поддерживать их? Если это не нужно?

Некоторые имена могут быть более ясными (например, nr как число) или не соответствуют соглашениям о стиле (название должно быть заголовком).

Основная ошибка, которую я бы сказал, заключается в том, чтобы хранить число внутри объекта вообще. Это хрупко, так как это означает, что вы постоянно обновляете его, когда вещи добавляются, удаляются и т. Д.

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

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

+0

Он должен также добавить модификаторы доступа к защищенным/приватным и создать геттеры/сеттеры. –

+0

@ GrégoryElhaimer Да, хороший момент. –

+0

Да, это скорее первоначальный эскиз, я при необходимости добавлю сеттеры и геттеры. Меня смущает одна вещь: кажется, что подклассам не нужно реализовывать какие-либо методы. –

3

Это на самом деле не правильный дизайн. (но мне нравится, как вы думаете о минимальном написании кода)

Книга не расширена главой или «элементами главы». Книга содержит главы, а также может содержать/делать что-то еще.

Поэтому правильный дизайн является Простейшая один

public class Book{ 
    private String title; 
    private List<Chapter> chapters; 
} 
//other classes would look similar 

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

Этот «феномен» также называют, это Composition over inheritance

+0

Итак, дизайн, который не использует наследование и просто полностью следует описанию книги, лучше? –

+0

Этот ответ неверен; «Книга» не расширяет «Глава». Он расширяет контейнер, который может содержать только 'Chapter'. –

+1

@ J.Doe - в этом случае состав над наследованием имеет гораздо больше смысла. – libik

5

Ваш первый подход довольно хорошо, но не принимает во внимание возможность эволюции.

Что произойдет, если мы попросим вас добавить возможность для абзацев иметь 0-n кавычек (или что-нибудь еще)? Что произойдет, если мы попросим вас добавить в вашу книгу тип главы, которая не может иметь подчин?

Это потребует значительных изменений. Вы должны посмотреть на composite pattern.

Следуя этому шаблону, вы будете более гибкими в плане эволюции.

Когда вы думаете о ООП, вы всегда должны помнить, что интерфейсы могут иметь огромную роль в том, как вы будете разрабатывать свой код. Многие из этих проблем уже решены и имеют условное решение (шаблоны проектирования). Вы должны потратить время на изучение наиболее распространенных из них. Это определенно изменит ваш подход к кодированию.

(«Дизайн головы образца первый» будет хорошей книгой для чтения).

Более того, одной из наиболее важных особенностей ООП является инкапсуляция. Это обеспечивает очень эффективный способ контроля доступности атрибутов класса. Вы ДОЛЖНЫ использовать его. Начните с добавления модификаторов private или protected атрибутов вашего класса и создания геттеров/сеттеров, необходимых для доступа/изменения этих атрибутов.

Еще одна вещь, которую следует учитывать: Невозможно использовать метод System.out.println() для регистрации вашего кода. Используйте log API (например, log4j) и исключения.

public void removeFromElement(int index) throws ChapterNotFoundException{ 
     if (index <= 0 && index > x.size()){ 
      throw new ChapterNotFoundException(String.format("Chapter %s does not exist", index)); 
     } 

     x.remove(index); 
     logger.info(String.format("Chapter %s has been removed", index)); 
    } 
1

Ваш дизайн хороший. В коде есть несколько ошибок; Я предлагаю написать несколько модульных тестов, чтобы найти их (подсказка: попробуйте удалить страницы).

Я написал программное обеспечение для обработки книг на нескольких языках (Java, Python, Groovy) и обнаружил, что это сложнее, чем кажется. Проблема в том, что все элементы (книга, глава, подраздел, параграф) имеют много общих черт, но тонкие различия. Большинство из них являются контейнерами для определенных типов других элементов (поэтому книга состоит из главы, но не абзацев). Только абзац не является контейнером. Все они имеют текст (название или текст абзаца), но семантика текста отличается. Кроме того, названия для суб-глав не имеют смысла, или они?

Это очень сложно придумать хороший API для обработки всех угловых шкафов без особого дублированного кода, особенно на языке Java, где у вас нет mixins.

Смежные вопросы