diff --git a/README.md b/README.md index 4f743b3..5fc9f8d 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,7 @@ 2. [Наблюдатель](observer/) 3. [Команда](command/) 4. [Шаблонный метод](templatemethod/) +5. [Итератор](iterator/) ### Структурные diff --git a/iterator/README.md b/iterator/README.md new file mode 100644 index 0000000..eb16825 --- /dev/null +++ b/iterator/README.md @@ -0,0 +1,23 @@ +# Итератор + +Поведенческий паттерн проектирования, который даёт возможность последовательно обходить элементы составных объектов, не раскрывая их внутреннего представления. + +Паттерн **Итератор** предоставляет меха­низм последовательного перебора элемен­тов кол­лекции без раскрытия ее внутрен­него представления. + +## Принципы + +- Класс должен иметь только одну причину для изменения + +Поручая классу не только его не­посредственную задачу (управление коллекцией объ­ектов), но и дополнительные задачи (перебор), создаются две возможные причины для изменения. Теперь измениться может как внутренняя реализация коллек­ции, так и механизм перебора. + +### Связность + +![coupling_cohesion.png](coupling_cohesion.png) + +Модуль или класс обладает ***высокой связностью*** (*high cohesion*), если он спроектирован для выполнения группы взаимосвязанных функций. Классы с ***низкой связностью*** (*low coupling*) проектируются на основе набора разрозненных функций. + +Классы, соответствующие принципу, обычно обладают высокой связностью, и более просты в сопровождении, чем классы с многими обязанностями и низкой связностью. + +## Схемы + +![scheme-1](scheme-1.png) diff --git a/iterator/coupling_cohesion.png b/iterator/coupling_cohesion.png new file mode 100644 index 0000000..b87f1d4 Binary files /dev/null and b/iterator/coupling_cohesion.png differ diff --git a/iterator/scheme-1.png b/iterator/scheme-1.png new file mode 100644 index 0000000..dde0c6e Binary files /dev/null and b/iterator/scheme-1.png differ diff --git a/iterator/simpleiterator/app.d b/iterator/simpleiterator/app.d new file mode 100644 index 0000000..d698071 --- /dev/null +++ b/iterator/simpleiterator/app.d @@ -0,0 +1,10 @@ +module app; + +import dinermenu, menu, waitress; + +void main() +{ + auto waitress = new Waitress(new DinerMenu()); + waitress.printMenu(); + waitress.printVegetarianMenu(); +} diff --git a/iterator/simpleiterator/dinermenu.d b/iterator/simpleiterator/dinermenu.d new file mode 100644 index 0000000..abd8708 --- /dev/null +++ b/iterator/simpleiterator/dinermenu.d @@ -0,0 +1,50 @@ +module dinermenu; + +import menu, menuitem, iterator, dinermenuiterator; +import std.stdio : writeln; + +class DinerMenu : Menu +{ + static const int MAX_ITEMS = 6; + private int numberOfItems = 0; + private MenuItem[] menuItems; + + this() + { + menuItems = new MenuItem[MAX_ITEMS]; + + addItem("Vegetarian BLT", "(Fakin') Bacon with lettuce & tomato on whole wheat", true, 2.99); + addItem("BLT", "Bacon with lettuce & tomato on whole wheat", false, 2.99); + addItem("Soup of the day", "Soup of the day, with a side of potato salad", false, 3.29); + addItem("Hotdog", "A hot dog, with sauerkraut, relish, onions, topped with cheese", false, 3.05); + addItem("Steamed Veggies and Brown Rice", "Steamed vegetables over brown rice", true, 3.99); + addItem("Pasta", "Spaghetti with Marinara Sauce, and a slice of sourdough bread", true, 3.89); + } + + void addItem(string name, string description, bool vegetarian, double price) + { + if (numberOfItems >= MAX_ITEMS) + { + writeln("Sorry, menu is full! Can't add item to menu"); + } + else + { + menuItems[numberOfItems++] = new MenuItem(name, description, vegetarian, price); + } + } + + MenuItem[] getMenuItems() + { + return menuItems; + } + + override Iterator createIterator() + { + return new DinerMenuIterator(menuItems); + } + + override string toString() const @safe pure nothrow + { + return "Diner Menu"; + } +} diff --git a/iterator/simpleiterator/dinermenuiterator.d b/iterator/simpleiterator/dinermenuiterator.d new file mode 100644 index 0000000..ca08209 --- /dev/null +++ b/iterator/simpleiterator/dinermenuiterator.d @@ -0,0 +1,24 @@ +module dinermenuiterator; + +import iterator, menuitem; + +class DinerMenuIterator : Iterator +{ + private MenuItem[] items; + private int position; + + this(MenuItem[] items) + { + this.items = items; + } + + override MenuItem next() + { + return items[position++]; + } + + override bool hasNext() + { + return items.length > position; + } +} diff --git a/iterator/simpleiterator/iterator.d b/iterator/simpleiterator/iterator.d new file mode 100644 index 0000000..c784970 --- /dev/null +++ b/iterator/simpleiterator/iterator.d @@ -0,0 +1,9 @@ +module iterator; + +import menuitem; + +interface Iterator +{ + bool hasNext(); + MenuItem next(); +} diff --git a/iterator/simpleiterator/menu.d b/iterator/simpleiterator/menu.d new file mode 100644 index 0000000..6d4dfa0 --- /dev/null +++ b/iterator/simpleiterator/menu.d @@ -0,0 +1,8 @@ +module menu; + +import iterator; + +interface Menu +{ + Iterator createIterator(); +} diff --git a/iterator/simpleiterator/menuitem.d b/iterator/simpleiterator/menuitem.d new file mode 100644 index 0000000..8fc64f9 --- /dev/null +++ b/iterator/simpleiterator/menuitem.d @@ -0,0 +1,44 @@ +module menuitem; + +import std.conv : to; + +class MenuItem +{ + private string name; + private string description; + private bool vegetarian; + private double price; + + this(string name, string description, bool vegetarian, double price) + { + this.name = name; + this.description = description; + this.vegetarian = vegetarian; + this.price = price; + } + + string getName() + { + return name; + } + + string getDescription() + { + return description; + } + + double getPrice() + { + return price; + } + + bool isVegetarian() + { + return vegetarian; + } + + override string toString() const + { + return (name ~ ", $" ~ price.to!string ~ "\n " ~ description); + } +} diff --git a/iterator/simpleiterator/waitress.d b/iterator/simpleiterator/waitress.d new file mode 100644 index 0000000..16f7127 --- /dev/null +++ b/iterator/simpleiterator/waitress.d @@ -0,0 +1,79 @@ +module waitress; + +import menu, iterator, menuitem; +import std.stdio : writeln, write; + +class Waitress +{ + private Menu dinerMenu; + + this(Menu dinerMenu) + { + this.dinerMenu = dinerMenu; + } + + void printMenu() + { + writeln("MENU\n----\nLUNCH"); + printMenu(dinerMenu.createIterator()); + } + + private void printMenu(Iterator iterator) + { + while (iterator.hasNext()) + { + MenuItem menuItem = iterator.next(); + write(menuItem.getName(), ", "); + write(menuItem.getPrice(), " -- "); + writeln(menuItem.getDescription()); + } + } + + void printVegetarianMenu() + { + writeln("MENU\n----\nVEGETARIAN"); + printVegetarianMenu(dinerMenu.createIterator()); + } + + // bool isItemVegetarian(string name) + // { + // Iterator dinnerIterator = dinerMenu.createIterator(); + // if (isVegetarian(name, dinnerIterator)) + // { + // return true; + // } + + // return false; + // } + + + private void printVegetarianMenu(Iterator iterator) + { + while (iterator.hasNext()) + { + MenuItem menuItem = iterator.next(); + if (menuItem.isVegetarian()) + { + write(menuItem.getName()); + writeln("\t\t", menuItem.getPrice()); + writeln("\t", menuItem.getDescription()); + } + } + } + + // private bool isVegetarian(string name, Iterator iterator) + // { + // while (iterator.hasNext()) + // { + // MenuItem menuItem = iterator.next(); + // if (menuItem.getName() == name) + // { + // if (menuItem.isVegetarian()) + // { + // return true; + // } + // } + // } + // return false; + // } +}