commit 56c278cb44ddee4b4ac962223d0b10ebfdeb9b9b Author: Alexander Zhirov Date: Mon Dec 5 10:38:19 2022 +0300 new diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7a1b276 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +app +app.o diff --git a/Head-First-Design-Patterns-master.zip b/Head-First-Design-Patterns-master.zip new file mode 100644 index 0000000..079fd3b Binary files /dev/null and b/Head-First-Design-Patterns-master.zip differ diff --git a/README.md b/README.md new file mode 100644 index 0000000..948698d --- /dev/null +++ b/README.md @@ -0,0 +1,39 @@ +# Паттерны проектирования на языке D + +Паттерны проектирования по книге [Head First. Паттерны проектирования](https://ftp.zhirov.kz/books/IT/%D0%9F%D0%B0%D1%82%D1%82%D0%B5%D1%80%D0%BD%D1%8B/Head%20First.%20%D0%9F%D0%B0%D1%82%D1%82%D0%B5%D1%80%D0%BD%D1%8B%20%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F%20%28%D0%AD%D1%80%D0%B8%D0%BA%20%D0%A4%D1%80%D0%B8%D0%BC%D0%B5%D0%BD%2C%20%D0%AD%D0%BB%D0%B8%D0%B7%D0%B0%D0%B1%D0%B5%D1%82%20%D0%A0%D0%BE%D0%B1%D1%81%D0%BE%D0%BD%29%202022.pdf) ([исходный код на Java](Head-First-Design-Patterns-master.zip)) + +## Паттерны + +### Поведенческие + +1. [Стратегия](strategy/) +2. [Наблюдатель](observer/) +3. [Команда](command/) +4. [Шаблонный метод](templatemethod/) +5. [Итератор](iterator/) +6. [Состояние](state/) + +### Структурные + +1. [Декоратор](decorator/) +2. [Адаптер](adapter/) +3. [Фасад](facade/) +4. [Компоновщик](composite/) + +### Пораждающие + +1. [Фабричный метод (Простая фабрика)](factorymethod/) +2. [Абстрактная фабрика](abstractfactory/) +3. [Одиночка](singleton/) + +## Компиляция + +```sh +dmd *.d +``` + +или + +```sh +ldc2 *.d +``` diff --git a/abstractfactory/README.md b/abstractfactory/README.md new file mode 100644 index 0000000..46e663f --- /dev/null +++ b/abstractfactory/README.md @@ -0,0 +1,15 @@ +# Абстрактная фабрика + +Порождающий паттерн проектирования, который позволяет создавать семейства связанных объектов, не привязываясь к конкретным классам создаваемых объектов. + +Паттерн **Абстрактная Фабрика** предоставляет интерфейс создания семейств взаимосвязанных или взаимозависимых объектов без указания их конкретных классов. + +## Принципы + +- Код должен зависеть от абстракций, а не от конкретных классов + +## Схемы + +![scheme-1](scheme-1.png) + +![scheme-2](scheme-2.png) diff --git a/abstractfactory/app.d b/abstractfactory/app.d new file mode 100644 index 0000000..e76c91a --- /dev/null +++ b/abstractfactory/app.d @@ -0,0 +1,37 @@ +module abstractfactory.app; + +import abstractfactory.pizza; +import abstractfactory.pizzastore; +import abstractfactory.nypizzastore; +import abstractfactory.chicagopizzastore; +import std.stdio : writeln; + +void main() +{ + PizzaStore nyStore = new NYPizzaStore(); + PizzaStore chicagoStore = new ChicagoPizzaStore(); + + Pizza pizza = nyStore.orderPizza("cheese"); + writeln("Ethan ordered a ", pizza); + + pizza = chicagoStore.orderPizza("cheese"); + writeln("Joel ordered a ", pizza); + + pizza = nyStore.orderPizza("clam"); + writeln("Ethan ordered a ", pizza); + + pizza = chicagoStore.orderPizza("clam"); + writeln("Joel ordered a ", pizza); + + pizza = nyStore.orderPizza("pepperoni"); + writeln("Ethan ordered a ", pizza); + + pizza = chicagoStore.orderPizza("pepperoni"); + writeln("Joel ordered a ", pizza); + + pizza = nyStore.orderPizza("veggie"); + writeln("Ethan ordered a ", pizza); + + pizza = chicagoStore.orderPizza("veggie"); + writeln("Joel ordered a ", pizza); +} diff --git a/abstractfactory/blackolives.d b/abstractfactory/blackolives.d new file mode 100644 index 0000000..710e35a --- /dev/null +++ b/abstractfactory/blackolives.d @@ -0,0 +1,11 @@ +module abstractfactory.blackolives; + +import abstractfactory.veggies; + +class BlackOlives : Veggies +{ + override string toString() const @safe pure nothrow + { + return "Black Olives"; + } +} diff --git a/abstractfactory/cheese.d b/abstractfactory/cheese.d new file mode 100644 index 0000000..107f845 --- /dev/null +++ b/abstractfactory/cheese.d @@ -0,0 +1,9 @@ +module abstractfactory.cheese; + +interface Cheese +{ + string opBinary(string op : "~")(string s) const + { + return (cast(Object)this).toString() ~ s; + } +} diff --git a/abstractfactory/cheesepizza.d b/abstractfactory/cheesepizza.d new file mode 100644 index 0000000..28334d1 --- /dev/null +++ b/abstractfactory/cheesepizza.d @@ -0,0 +1,23 @@ +module abstractfactory.cheesepizza; + +import abstractfactory.pizza; +import abstractfactory.pizzaingredientfactory; +import std.stdio : writeln; + +class CheesePizza : Pizza +{ + PizzaIngredientFactory ingredientFactory; + + this(PizzaIngredientFactory ingredientFactory) + { + this.ingredientFactory = ingredientFactory; + } + + override void prepare() + { + writeln("Preparing ", name); + dough = ingredientFactory.createDough(); + sauce = ingredientFactory.createSauce(); + cheese = ingredientFactory.createCheese(); + } +} diff --git a/abstractfactory/chicagopizzaingredientfactory.d b/abstractfactory/chicagopizzaingredientfactory.d new file mode 100644 index 0000000..9de0d9e --- /dev/null +++ b/abstractfactory/chicagopizzaingredientfactory.d @@ -0,0 +1,51 @@ +module abstractfactory.chicagopizzaingredientfactory; + +import abstractfactory.pizzaingredientfactory; +import abstractfactory.dough; +import abstractfactory.thickcrustdough; +import abstractfactory.sauce; +import abstractfactory.plumtomatosauce; +import abstractfactory.cheese; +import abstractfactory.mozzarellacheese; +import abstractfactory.veggies; +import abstractfactory.blackolives; +import abstractfactory.spinach; +import abstractfactory.eggplant; +import abstractfactory.pepperoni; +import abstractfactory.slicedpepperoni; +import abstractfactory.clams; +import abstractfactory.frozenclams; + +class ChicagoPizzaIngredientFactory : PizzaIngredientFactory +{ + override Dough createDough() + { + return new ThinCrustDough(); + } + + override Sauce createSauce() + { + return new PlumTomatoSauce(); + } + + override Cheese createCheese() + { + return new MozzarellaCheese(); + } + + override Veggies[] createVeggies() + { + Veggies[] veggies = cast(Veggies[])[ new BlackOlives(), new Spinach(), new Eggplant() ]; + return veggies; + } + + override Pepperoni createPepperoni() + { + return new SlicedPepperoni(); + } + + override Clams createClam() + { + return new FrozenClams(); + } +} diff --git a/abstractfactory/chicagopizzastore.d b/abstractfactory/chicagopizzastore.d new file mode 100644 index 0000000..897712e --- /dev/null +++ b/abstractfactory/chicagopizzastore.d @@ -0,0 +1,43 @@ +module abstractfactory.chicagopizzastore; + +import abstractfactory.pizza; +import abstractfactory.pizzastore; +import abstractfactory.pizzaingredientfactory; +import abstractfactory.chicagopizzaingredientfactory; +import abstractfactory.cheesepizza; +import abstractfactory.veggiepizza; +import abstractfactory.clampizza; +import abstractfactory.pepperonipizza; + +class ChicagoPizzaStore : PizzaStore +{ +protected: + override Pizza createPizza(string item) + { + Pizza pizza; + PizzaIngredientFactory ingredientFactory = new ChicagoPizzaIngredientFactory(); + + if (item == "cheese") + { + pizza = new CheesePizza(ingredientFactory); + pizza.setName("Chicago Style Cheese Pizza"); + } + else if (item == "veggie") + { + pizza = new VeggiePizza(ingredientFactory); + pizza.setName("Chicago Style Veggie Pizza"); + } + else if (item == "clam") + { + pizza = new ClamPizza(ingredientFactory); + pizza.setName("Chicago Style Clam Pizza"); + } + else if (item == "pepperoni") + { + pizza = new PepperoniPizza(ingredientFactory); + pizza.setName("Chicago Style Pepperoni Pizza"); + } + + return pizza; + } +} diff --git a/abstractfactory/clampizza.d b/abstractfactory/clampizza.d new file mode 100644 index 0000000..fb4eab4 --- /dev/null +++ b/abstractfactory/clampizza.d @@ -0,0 +1,24 @@ +module abstractfactory.clampizza; + +import abstractfactory.pizza; +import abstractfactory.pizzaingredientfactory; +import std.stdio : writeln; + +class ClamPizza : Pizza +{ + PizzaIngredientFactory ingredientFactory; + + this(PizzaIngredientFactory ingredientFactory) + { + this.ingredientFactory = ingredientFactory; + } + + override void prepare() + { + writeln("Preparing ", name); + dough = ingredientFactory.createDough(); + sauce = ingredientFactory.createSauce(); + cheese = ingredientFactory.createCheese(); + clams = ingredientFactory.createClam(); + } +} diff --git a/abstractfactory/clams.d b/abstractfactory/clams.d new file mode 100644 index 0000000..0d79ec4 --- /dev/null +++ b/abstractfactory/clams.d @@ -0,0 +1,9 @@ +module abstractfactory.clams; + +interface Clams +{ + string opBinary(string op : "~")(string s) const + { + return (cast(Object)this).toString() ~ s; + } +} diff --git a/abstractfactory/dough.d b/abstractfactory/dough.d new file mode 100644 index 0000000..d6f28d5 --- /dev/null +++ b/abstractfactory/dough.d @@ -0,0 +1,9 @@ +module abstractfactory.dough; + +interface Dough +{ + string opBinary(string op : "~")(string s) const + { + return (cast(Object)this).toString() ~ s; + } +} diff --git a/abstractfactory/eggplant.d b/abstractfactory/eggplant.d new file mode 100644 index 0000000..4eb6974 --- /dev/null +++ b/abstractfactory/eggplant.d @@ -0,0 +1,11 @@ +module abstractfactory.eggplant; + +import abstractfactory.veggies; + +class Eggplant : Veggies +{ + override string toString() const @safe pure nothrow + { + return "Eggplant"; + } +} diff --git a/abstractfactory/freshclams.d b/abstractfactory/freshclams.d new file mode 100644 index 0000000..28fb1dd --- /dev/null +++ b/abstractfactory/freshclams.d @@ -0,0 +1,11 @@ +module abstractfactory.freshclams; + +import abstractfactory.clams; + +class FreshClams : Clams +{ + override string toString() const @safe pure nothrow + { + return "Fresh Clams from Long Island Sound"; + } +} diff --git a/abstractfactory/frozenclams.d b/abstractfactory/frozenclams.d new file mode 100644 index 0000000..09431af --- /dev/null +++ b/abstractfactory/frozenclams.d @@ -0,0 +1,11 @@ +module abstractfactory.frozenclams; + +import abstractfactory.clams; + +class FrozenClams : Clams +{ + override string toString() const @safe pure nothrow + { + return "Frozen Clams from Chesapeake Bay"; + } +} diff --git a/abstractfactory/garlic.d b/abstractfactory/garlic.d new file mode 100644 index 0000000..0bdf72a --- /dev/null +++ b/abstractfactory/garlic.d @@ -0,0 +1,11 @@ +module abstractfactory.garlic; + +import abstractfactory.veggies; + +class Garlic : Veggies +{ + override string toString() const @safe pure nothrow + { + return "Garlic"; + } +} diff --git a/abstractfactory/marinarasauce.d b/abstractfactory/marinarasauce.d new file mode 100644 index 0000000..39754d3 --- /dev/null +++ b/abstractfactory/marinarasauce.d @@ -0,0 +1,11 @@ +module abstractfactory.marinarasauce; + +import abstractfactory.sauce; + +class MarinaraSauce : Sauce +{ + override string toString() const @safe pure nothrow + { + return "Marinara Sauce"; + } +} diff --git a/abstractfactory/mozzarellacheese.d b/abstractfactory/mozzarellacheese.d new file mode 100644 index 0000000..20aa408 --- /dev/null +++ b/abstractfactory/mozzarellacheese.d @@ -0,0 +1,11 @@ +module abstractfactory.mozzarellacheese; + +import abstractfactory.cheese; + +class MozzarellaCheese : Cheese +{ + override string toString() const @safe pure nothrow + { + return "Shredded Mozzarella"; + } +} diff --git a/abstractfactory/mushroom.d b/abstractfactory/mushroom.d new file mode 100644 index 0000000..ce53b44 --- /dev/null +++ b/abstractfactory/mushroom.d @@ -0,0 +1,11 @@ +module abstractfactory.mushroom; + +import abstractfactory.veggies; + +class Mushroom : Veggies +{ + override string toString() const @safe pure nothrow + { + return "Mushroom"; + } +} diff --git a/abstractfactory/nypizzaingredientfactory.d b/abstractfactory/nypizzaingredientfactory.d new file mode 100644 index 0000000..2017e20 --- /dev/null +++ b/abstractfactory/nypizzaingredientfactory.d @@ -0,0 +1,52 @@ +module abstractfactory.nypizzaingredientfactory; + +import abstractfactory.pizzaingredientfactory; +import abstractfactory.dough; +import abstractfactory.thincrustdough; +import abstractfactory.sauce; +import abstractfactory.marinarasauce; +import abstractfactory.cheese; +import abstractfactory.reggianocheese; +import abstractfactory.veggies; +import abstractfactory.garlic; +import abstractfactory.onion; +import abstractfactory.mushroom; +import abstractfactory.redpepper; +import abstractfactory.pepperoni; +import abstractfactory.slicedpepperoni; +import abstractfactory.clams; +import abstractfactory.freshclams; + +class NYPizzaIngredientFactory : PizzaIngredientFactory +{ + override Dough createDough() + { + return new ThinCrustDough(); + } + + override Sauce createSauce() + { + return new MarinaraSauce(); + } + + override Cheese createCheese() + { + return new ReggianoCheese(); + } + + override Veggies[] createVeggies() + { + Veggies[] veggies = cast(Veggies[])[ new Garlic(), new Onion(), new Mushroom(), new RedPepper() ]; + return veggies; + } + + override Pepperoni createPepperoni() + { + return new SlicedPepperoni(); + } + + override Clams createClam() + { + return new FreshClams(); + } +} diff --git a/abstractfactory/nypizzastore.d b/abstractfactory/nypizzastore.d new file mode 100644 index 0000000..76a012b --- /dev/null +++ b/abstractfactory/nypizzastore.d @@ -0,0 +1,43 @@ +module abstractfactory.nypizzastore; + +import abstractfactory.pizza; +import abstractfactory.pizzastore; +import abstractfactory.pizzaingredientfactory; +import abstractfactory.nypizzaingredientfactory; +import abstractfactory.cheesepizza; +import abstractfactory.veggiepizza; +import abstractfactory.clampizza; +import abstractfactory.pepperonipizza; + +class NYPizzaStore : PizzaStore +{ +protected: + override Pizza createPizza(string item) + { + Pizza pizza; + PizzaIngredientFactory ingredientFactory = new NYPizzaIngredientFactory(); + + if (item == "cheese") + { + pizza = new CheesePizza(ingredientFactory); + pizza.setName("New York Style Cheese Pizza"); + } + else if (item == "veggie") + { + pizza = new VeggiePizza(ingredientFactory); + pizza.setName("New York Style Veggie Pizza"); + } + else if (item == "clam") + { + pizza = new ClamPizza(ingredientFactory); + pizza.setName("New York Style Clam Pizza"); + } + else if (item == "pepperoni") + { + pizza = new PepperoniPizza(ingredientFactory); + pizza.setName("New York Style Pepperoni Pizza"); + } + + return pizza; + } +} diff --git a/abstractfactory/onion.d b/abstractfactory/onion.d new file mode 100644 index 0000000..0c14829 --- /dev/null +++ b/abstractfactory/onion.d @@ -0,0 +1,11 @@ +module abstractfactory.onion; + +import abstractfactory.veggies; + +class Onion : Veggies +{ + override string toString() const @safe pure nothrow + { + return "Onion"; + } +} diff --git a/abstractfactory/pepperoni.d b/abstractfactory/pepperoni.d new file mode 100644 index 0000000..9f94003 --- /dev/null +++ b/abstractfactory/pepperoni.d @@ -0,0 +1,9 @@ +module abstractfactory.pepperoni; + +interface Pepperoni +{ + string opBinary(string op : "~")(string s) const + { + return (cast(Object)this).toString() ~ s; + } +} \ No newline at end of file diff --git a/abstractfactory/pepperonipizza.d b/abstractfactory/pepperonipizza.d new file mode 100644 index 0000000..192c9d9 --- /dev/null +++ b/abstractfactory/pepperonipizza.d @@ -0,0 +1,25 @@ +module abstractfactory.pepperonipizza; + +import abstractfactory.pizza; +import abstractfactory.pizzaingredientfactory; +import std.stdio : writeln; + +class PepperoniPizza : Pizza +{ + PizzaIngredientFactory ingredientFactory; + + this(PizzaIngredientFactory ingredientFactory) + { + this.ingredientFactory = ingredientFactory; + } + + override void prepare() + { + writeln("Preparing ", name); + dough = ingredientFactory.createDough(); + sauce = ingredientFactory.createSauce(); + cheese = ingredientFactory.createCheese(); + veggies = ingredientFactory.createVeggies(); + pepperoni = ingredientFactory.createPepperoni(); + } +} diff --git a/abstractfactory/pizza.d b/abstractfactory/pizza.d new file mode 100644 index 0000000..d7cdfaa --- /dev/null +++ b/abstractfactory/pizza.d @@ -0,0 +1,88 @@ +module abstractfactory.pizza; + +import abstractfactory.dough; +import abstractfactory.sauce; +import abstractfactory.veggies; +import abstractfactory.cheese; +import abstractfactory.pepperoni; +import abstractfactory.clams; +import std.stdio : writeln; +import std.conv : to; + +abstract class Pizza +{ +protected: + string name; + Dough dough; + Sauce sauce; + Veggies[] veggies; + Cheese cheese; + Pepperoni pepperoni; + Clams clams; +public: + void prepare(); + + void bake() + { + writeln("Bake for 25 minutes at 350"); + } + + void cut() + { + writeln("Cut the pizza into diagonal slices"); + } + + void box() + { + writeln("Place pizza in official PizzaStore box"); + } + + void setName(string name) + { + this.name = name; + } + + string getName() + { + return name; + } + + override string toString() const + { + string s; + s ~= "---- " ~ name ~ " ----\n"; + if (dough !is null) + { + s ~= dough ~ "\n"; + } + if (sauce !is null) + { + s ~= sauce ~ "\n"; + } + if (cheese !is null) + { + s ~= cheese ~ "\n"; + } + if (veggies.length) + { + foreach (key, val; veggies) + { + s ~= val.to!string; + if (key + 1 < veggies.length) + { + s ~= ", "; + } + } + } + if (clams !is null) + { + s ~= clams ~ "\n"; + } + if (pepperoni !is null) + { + s ~= pepperoni ~ "\n"; + } + + return s; + } +} diff --git a/abstractfactory/pizzaingredientfactory.d b/abstractfactory/pizzaingredientfactory.d new file mode 100644 index 0000000..050fca6 --- /dev/null +++ b/abstractfactory/pizzaingredientfactory.d @@ -0,0 +1,18 @@ +module abstractfactory.pizzaingredientfactory; + +import abstractfactory.dough; +import abstractfactory.sauce; +import abstractfactory.cheese; +import abstractfactory.veggies; +import abstractfactory.pepperoni; +import abstractfactory.clams; + +interface PizzaIngredientFactory +{ + Dough createDough(); + Sauce createSauce(); + Cheese createCheese(); + Veggies[] createVeggies(); + Pepperoni createPepperoni(); + Clams createClam(); +} diff --git a/abstractfactory/pizzastore.d b/abstractfactory/pizzastore.d new file mode 100644 index 0000000..315f0b2 --- /dev/null +++ b/abstractfactory/pizzastore.d @@ -0,0 +1,24 @@ +module abstractfactory.pizzastore; + +import abstractfactory.pizza; +import std.stdio : writeln; + +abstract class PizzaStore +{ +protected: + Pizza createPizza(string item); +public: + Pizza orderPizza(string type) + { + Pizza pizza = createPizza(type); + + writeln("--- Making a " ~ pizza.getName() ~ " ---"); + + pizza.prepare(); + pizza.bake(); + pizza.cut(); + pizza.box(); + + return pizza; + } +} diff --git a/abstractfactory/plumtomatosauce.d b/abstractfactory/plumtomatosauce.d new file mode 100644 index 0000000..e1d857f --- /dev/null +++ b/abstractfactory/plumtomatosauce.d @@ -0,0 +1,11 @@ +module abstractfactory.plumtomatosauce; + +import abstractfactory.sauce; + +class PlumTomatoSauce : Sauce +{ + override string toString() const @safe pure nothrow + { + return "Tomato sauce with plum tomatoes"; + } +} diff --git a/abstractfactory/redpepper.d b/abstractfactory/redpepper.d new file mode 100644 index 0000000..1b5ace2 --- /dev/null +++ b/abstractfactory/redpepper.d @@ -0,0 +1,11 @@ +module abstractfactory.redpepper; + +import abstractfactory.veggies; + +class RedPepper : Veggies +{ + override string toString() const @safe pure nothrow + { + return "Red Pepper"; + } +} diff --git a/abstractfactory/reggianocheese.d b/abstractfactory/reggianocheese.d new file mode 100644 index 0000000..f999d37 --- /dev/null +++ b/abstractfactory/reggianocheese.d @@ -0,0 +1,11 @@ +module abstractfactory.reggianocheese; + +import abstractfactory.cheese; + +class ReggianoCheese : Cheese +{ + override string toString() const @safe pure nothrow + { + return "Reggiano Cheese"; + } +} diff --git a/abstractfactory/sauce.d b/abstractfactory/sauce.d new file mode 100644 index 0000000..5d447d1 --- /dev/null +++ b/abstractfactory/sauce.d @@ -0,0 +1,9 @@ +module abstractfactory.sauce; + +interface Sauce +{ + string opBinary(string op : "~")(string s) const + { + return (cast(Object)this).toString() ~ s; + } +} \ No newline at end of file diff --git a/abstractfactory/scheme-1.png b/abstractfactory/scheme-1.png new file mode 100644 index 0000000..a6016c1 Binary files /dev/null and b/abstractfactory/scheme-1.png differ diff --git a/abstractfactory/scheme-2.png b/abstractfactory/scheme-2.png new file mode 100644 index 0000000..c05fd1c Binary files /dev/null and b/abstractfactory/scheme-2.png differ diff --git a/abstractfactory/slicedpepperoni.d b/abstractfactory/slicedpepperoni.d new file mode 100644 index 0000000..becc98a --- /dev/null +++ b/abstractfactory/slicedpepperoni.d @@ -0,0 +1,11 @@ +module abstractfactory.slicedpepperoni; + +import abstractfactory.pepperoni; + +class SlicedPepperoni : Pepperoni +{ + override string toString() const @safe pure nothrow + { + return "Sliced Pepperoni"; + } +} diff --git a/abstractfactory/spinach.d b/abstractfactory/spinach.d new file mode 100644 index 0000000..4385f5a --- /dev/null +++ b/abstractfactory/spinach.d @@ -0,0 +1,11 @@ +module abstractfactory.spinach; + +import abstractfactory.veggies; + +class Spinach : Veggies +{ + override string toString() const @safe pure nothrow + { + return "Spinach"; + } +} diff --git a/abstractfactory/thickcrustdough.d b/abstractfactory/thickcrustdough.d new file mode 100644 index 0000000..104656e --- /dev/null +++ b/abstractfactory/thickcrustdough.d @@ -0,0 +1,16 @@ +module abstractfactory.thickcrustdough; + +import abstractfactory.dough; + +class ThinCrustDough : Dough +{ + override string toString() const @safe pure nothrow + { + return "ThickCrust style extra thick crust dough"; + } + + string opBinary(string op : "~")(string s) + { + return (cast(Object)this).toString() ~ s; + } +} diff --git a/abstractfactory/thincrustdough.d b/abstractfactory/thincrustdough.d new file mode 100644 index 0000000..ca854e3 --- /dev/null +++ b/abstractfactory/thincrustdough.d @@ -0,0 +1,16 @@ +module abstractfactory.thincrustdough; + +import abstractfactory.dough; + +class ThinCrustDough : Dough +{ + override string toString() const @safe pure nothrow + { + return "Thin Crust Dough"; + } + + string opBinary(string op : "~")(string s) + { + return (cast(Object)this).toString() ~ s; + } +} diff --git a/abstractfactory/veggiepizza.d b/abstractfactory/veggiepizza.d new file mode 100644 index 0000000..ae40a9c --- /dev/null +++ b/abstractfactory/veggiepizza.d @@ -0,0 +1,24 @@ +module abstractfactory.veggiepizza; + +import abstractfactory.pizza; +import abstractfactory.pizzaingredientfactory; +import std.stdio : writeln; + +class VeggiePizza : Pizza +{ + PizzaIngredientFactory ingredientFactory; + + this(PizzaIngredientFactory ingredientFactory) + { + this.ingredientFactory = ingredientFactory; + } + + override void prepare() + { + writeln("Preparing ", name); + dough = ingredientFactory.createDough(); + sauce = ingredientFactory.createSauce(); + cheese = ingredientFactory.createCheese(); + veggies = ingredientFactory.createVeggies(); + } +} diff --git a/abstractfactory/veggies.d b/abstractfactory/veggies.d new file mode 100644 index 0000000..20be41e --- /dev/null +++ b/abstractfactory/veggies.d @@ -0,0 +1,9 @@ +module abstractfactory.veggies; + +interface Veggies +{ + string opBinary(string op : "~")(string s) const + { + return (cast(Object)this).toString() ~ s; + } +} diff --git a/adapter/README.md b/adapter/README.md new file mode 100644 index 0000000..755074f --- /dev/null +++ b/adapter/README.md @@ -0,0 +1,19 @@ +# Адаптер + +Структурный паттерн проектирования, который позволяет объектам с несовместимыми интерфейсами работать вместе. + +Паттерн **Адаптер** преобразует интерфейс класса к другому интерфейсу, на который рассчитан клиент. Адаптер обеспечивает совместную работу классов, невозможную в обычных условиях из-за несовместимости интерфейсов. + +## Схемы + +![scheme-1](scheme-1.png) + +![scheme-2](scheme-2.png) + +![scheme-3](scheme-3.png) + +![scheme-4](scheme-4.png) + +![scheme-5](scheme-5.png) + +![scheme-6](scheme-6.png) diff --git a/adapter/scheme-1.png b/adapter/scheme-1.png new file mode 100644 index 0000000..263b71a Binary files /dev/null and b/adapter/scheme-1.png differ diff --git a/adapter/scheme-2.png b/adapter/scheme-2.png new file mode 100644 index 0000000..733f805 Binary files /dev/null and b/adapter/scheme-2.png differ diff --git a/adapter/scheme-3.png b/adapter/scheme-3.png new file mode 100644 index 0000000..45d1d1b Binary files /dev/null and b/adapter/scheme-3.png differ diff --git a/adapter/scheme-4.png b/adapter/scheme-4.png new file mode 100644 index 0000000..89989b8 Binary files /dev/null and b/adapter/scheme-4.png differ diff --git a/adapter/scheme-5.png b/adapter/scheme-5.png new file mode 100644 index 0000000..44cad3a Binary files /dev/null and b/adapter/scheme-5.png differ diff --git a/adapter/scheme-6.png b/adapter/scheme-6.png new file mode 100644 index 0000000..a0c09c4 Binary files /dev/null and b/adapter/scheme-6.png differ diff --git a/adapter/simpleadapter/app.d b/adapter/simpleadapter/app.d new file mode 100644 index 0000000..91309ee --- /dev/null +++ b/adapter/simpleadapter/app.d @@ -0,0 +1,28 @@ +module app; + +import lib; +import std.stdio : writeln; + +void main() +{ + Duck duck = new MallardDuck(); + + Turkey turkey = new WildTurkey(); + Duck turkeyAdapter = new TurkeyAdapter(turkey); + + writeln("The Turkey says..."); + turkey.gobble(); + turkey.fly(); + + writeln("\nThe Duck says..."); + testDuck(duck); + + writeln("\nThe TurkeyAdapter says..."); + testDuck(turkeyAdapter); +} + +void testDuck(Duck duck) +{ + duck.quack(); + duck.fly(); +} diff --git a/adapter/simpleadapter/lib/duck.d b/adapter/simpleadapter/lib/duck.d new file mode 100644 index 0000000..bb2ad78 --- /dev/null +++ b/adapter/simpleadapter/lib/duck.d @@ -0,0 +1,7 @@ +module lib.duck; + +interface Duck +{ + void quack(); + void fly(); +} diff --git a/adapter/simpleadapter/lib/mallarduck.d b/adapter/simpleadapter/lib/mallarduck.d new file mode 100644 index 0000000..5a7cbae --- /dev/null +++ b/adapter/simpleadapter/lib/mallarduck.d @@ -0,0 +1,17 @@ +module lib.mallarduck; + +import lib.duck; +import std.stdio : writeln; + +class MallardDuck : Duck +{ + void quack() + { + writeln("Quack!"); + } + + void fly() + { + writeln("I'm flying"); + } +} diff --git a/adapter/simpleadapter/lib/package.d b/adapter/simpleadapter/lib/package.d new file mode 100644 index 0000000..e5d953b --- /dev/null +++ b/adapter/simpleadapter/lib/package.d @@ -0,0 +1,7 @@ +module lib; + +public import lib.duck; +public import lib.mallarduck; +public import lib.turkey; +public import lib.turkeyadapter; +public import lib.wildturkey; diff --git a/adapter/simpleadapter/lib/turkey.d b/adapter/simpleadapter/lib/turkey.d new file mode 100644 index 0000000..46f6858 --- /dev/null +++ b/adapter/simpleadapter/lib/turkey.d @@ -0,0 +1,7 @@ +module lib.turkey; + +interface Turkey +{ + void gobble(); + void fly(); +} diff --git a/adapter/simpleadapter/lib/turkeyadapter.d b/adapter/simpleadapter/lib/turkeyadapter.d new file mode 100644 index 0000000..3c6726a --- /dev/null +++ b/adapter/simpleadapter/lib/turkeyadapter.d @@ -0,0 +1,27 @@ +module lib.turkeyadapter; + +import lib.turkey; +import lib.duck; + +class TurkeyAdapter : Duck +{ + Turkey turkey; + + this(Turkey turkey) + { + this.turkey = turkey; + } + + void quack() + { + turkey.gobble(); + } + + void fly() + { + foreach (val; 0..5) + { + turkey.fly(); + } + } +} diff --git a/adapter/simpleadapter/lib/wildturkey.d b/adapter/simpleadapter/lib/wildturkey.d new file mode 100644 index 0000000..da45f58 --- /dev/null +++ b/adapter/simpleadapter/lib/wildturkey.d @@ -0,0 +1,17 @@ +module lib.wildturkey; + +import lib.turkey; +import std.stdio : writeln; + +class WildTurkey : Turkey +{ + void gobble() + { + writeln("Gobble gobble"); + } + + void fly() + { + writeln("I'm flying a short distance"); + } +} diff --git a/command/README.md b/command/README.md new file mode 100644 index 0000000..f191639 --- /dev/null +++ b/command/README.md @@ -0,0 +1,13 @@ +# Команда + +Поведенческий паттерн проектирования, который превращает запросы в объекты, позволяя передавать их как аргументы при вызове методов, ставить запросы в очередь, логировать их, а также поддерживать отмену операций. + +Паттерн **Команда** инкапсулирует запрос в виде объекта, делая возможной параметризацию клиентских объектов с другими запросами, организацию очереди или регистрацию запросов, а также поддержку отмены операций. + +## Схемы + +![scheme-1](scheme-1.png) + +![scheme-2](scheme-2.png) + +![scheme-3](scheme-3.png) diff --git a/command/remote/app.d b/command/remote/app.d new file mode 100644 index 0000000..4b2632f --- /dev/null +++ b/command/remote/app.d @@ -0,0 +1,57 @@ +module command.remote.app; + +import command.remote.remotecontrol; +import command.remote.lightoncommand; +import command.remote.lightoffcommand; +import command.remote.light; +import command.remote.ceilingfan; +import command.remote.ceilingfanoffcommand; +import command.remote.ceilingfanoncommand; +import command.remote.garagedoorupcommand; +import command.remote.garagedoordowncommand; +import command.remote.garagedoor; +import command.remote.stereoonwithcdcommand; +import command.remote.stereo; +import command.remote.stereooffcommand; +import std.stdio : writeln; + +void main() +{ + auto remoteControl = new RemoteControl(); + + auto livingRoomLight = new Light("Living Room"); + auto kitchenLight = new Light("Kitchen"); + auto ceilingFan = new CeilingFan("Living Room"); + auto garageDoor = new GarageDoor("Garage"); + auto stereo = new Stereo("Living Room"); + + auto livingRoomLightOn = new LightOnCommand(livingRoomLight); + auto livingRoomLightOff = new LightOffCommand(livingRoomLight); + auto kitchenLightOn = new LightOnCommand(kitchenLight); + auto kitchenLightOff = new LightOffCommand(kitchenLight); + auto ceilingFanOn = new CeilingFanOnCommand(ceilingFan); + auto ceilingFanOff = new CeilingFanOffCommand(ceilingFan); + auto garageDoorUp = new GarageDoorUpCommand(garageDoor); + auto garageDoorDown = new GarageDoorDownCommand(garageDoor); + auto stereoOnWithCD = new StereoOnWithCDCommand(stereo); + auto stereoOff = new StereoOffCommand(stereo); + + remoteControl.setCommand(0, livingRoomLightOn, livingRoomLightOff); + remoteControl.setCommand(1, kitchenLightOn, kitchenLightOff); + remoteControl.setCommand(2, ceilingFanOn, ceilingFanOff); + remoteControl.setCommand(3, stereoOnWithCD, stereoOff); + remoteControl.setCommand(4, garageDoorUp, garageDoorDown); + + writeln(remoteControl); + + remoteControl.onButtonWasPressed(0); + remoteControl.offButtonWasPressed(0); + remoteControl.onButtonWasPressed(1); + remoteControl.offButtonWasPressed(1); + remoteControl.onButtonWasPressed(2); + remoteControl.offButtonWasPressed(2); + remoteControl.onButtonWasPressed(3); + remoteControl.offButtonWasPressed(3); + remoteControl.onButtonWasPressed(4); + remoteControl.offButtonWasPressed(4); +} diff --git a/command/remote/ceilingfan.d b/command/remote/ceilingfan.d new file mode 100644 index 0000000..6e68c77 --- /dev/null +++ b/command/remote/ceilingfan.d @@ -0,0 +1,48 @@ +module command.remote.ceilingfan; + +import std.stdio : writeln; + +class CeilingFan +{ + private string location; + private int level; + + static int HIGH = 2; + static int MEDIUM = 1; + static int LOW = 0; + + this(string location) + { + this.location = location; + } + + void high() + { + level = HIGH; + writeln(location ~ " ceiling fan is on high"); + + } + + void medium() + { + level = MEDIUM; + writeln(location ~ " ceiling fan is on medium"); + } + + void low() + { + level = LOW; + writeln(location ~ " ceiling fan is on low"); + } + + void off() + { + level = 0; + writeln(location ~ " ceiling fan is off"); + } + + int getSpeed() + { + return level; + } +} diff --git a/command/remote/ceilingfanoffcommand.d b/command/remote/ceilingfanoffcommand.d new file mode 100644 index 0000000..374160a --- /dev/null +++ b/command/remote/ceilingfanoffcommand.d @@ -0,0 +1,19 @@ +module command.remote.ceilingfanoffcommand; + +import command.remote.command; +import command.remote.ceilingfan; + +class CeilingFanOffCommand : Command +{ + CeilingFan ceilingFan; + + this(CeilingFan ceilingFan) + { + this.ceilingFan = ceilingFan; + } + + override void execute() + { + ceilingFan.off(); + } +} diff --git a/command/remote/ceilingfanoncommand.d b/command/remote/ceilingfanoncommand.d new file mode 100644 index 0000000..bd103be --- /dev/null +++ b/command/remote/ceilingfanoncommand.d @@ -0,0 +1,19 @@ +module command.remote.ceilingfanoncommand; + +import command.remote.command; +import command.remote.ceilingfan; + +class CeilingFanOnCommand : Command +{ + CeilingFan ceilingFan; + + this(CeilingFan ceilingFan) + { + this.ceilingFan = ceilingFan; + } + + override void execute() + { + ceilingFan.high(); + } +} diff --git a/command/remote/command.d b/command/remote/command.d new file mode 100644 index 0000000..6ff373c --- /dev/null +++ b/command/remote/command.d @@ -0,0 +1,6 @@ +module command.remote.command; + +interface Command +{ + void execute(); +} diff --git a/command/remote/garagedoor.d b/command/remote/garagedoor.d new file mode 100644 index 0000000..0acc4c3 --- /dev/null +++ b/command/remote/garagedoor.d @@ -0,0 +1,38 @@ +module command.remote.garagedoor; + +import std.stdio : writeln; + +class GarageDoor +{ + private string location; + + this(string location) + { + this.location = location; + } + + void up() + { + writeln(location ~ " garage Door is Up"); + } + + void down() + { + writeln(location ~ " garage Door is Down"); + } + + void stop() + { + writeln(location ~ " garage Door is Stopped"); + } + + void lightOn() + { + writeln(location ~ " garage light is on"); + } + + void lightOff() + { + writeln(location ~ " garage light is off"); + } +} diff --git a/command/remote/garagedoordowncommand.d b/command/remote/garagedoordowncommand.d new file mode 100644 index 0000000..2080815 --- /dev/null +++ b/command/remote/garagedoordowncommand.d @@ -0,0 +1,19 @@ +module command.remote.garagedoordowncommand; + +import command.remote.command; +import command.remote.garagedoor; + +class GarageDoorDownCommand : Command +{ + GarageDoor garageDoor; + + this(GarageDoor garageDoor) + { + this.garageDoor = garageDoor; + } + + override void execute() + { + garageDoor.down(); + } +} diff --git a/command/remote/garagedoorupcommand.d b/command/remote/garagedoorupcommand.d new file mode 100644 index 0000000..bbe7d71 --- /dev/null +++ b/command/remote/garagedoorupcommand.d @@ -0,0 +1,19 @@ +module command.remote.garagedoorupcommand; + +import command.remote.command; +import command.remote.garagedoor; + +class GarageDoorUpCommand : Command +{ + GarageDoor garageDoor; + + this(GarageDoor garageDoor) + { + this.garageDoor = garageDoor; + } + + override void execute() + { + garageDoor.up(); + } +} diff --git a/command/remote/light.d b/command/remote/light.d new file mode 100644 index 0000000..ada1b47 --- /dev/null +++ b/command/remote/light.d @@ -0,0 +1,23 @@ +module command.remote.light; + +import std.stdio : writeln; + +class Light +{ + private string location; + + this(string location) + { + this.location = location; + } + + void on() + { + writeln(location ~ " light is On"); + } + + void off() + { + writeln(location ~ " light is Off"); + } +} diff --git a/command/remote/lightoffcommand.d b/command/remote/lightoffcommand.d new file mode 100644 index 0000000..3124c74 --- /dev/null +++ b/command/remote/lightoffcommand.d @@ -0,0 +1,19 @@ +module command.remote.lightoffcommand; + +import command.remote.command; +import command.remote.light; + +class LightOffCommand : Command +{ + Light light; + + this(Light light) + { + this.light = light; + } + + override void execute() + { + light.off(); + } +} diff --git a/command/remote/lightoncommand.d b/command/remote/lightoncommand.d new file mode 100644 index 0000000..9fa2298 --- /dev/null +++ b/command/remote/lightoncommand.d @@ -0,0 +1,19 @@ +module command.remote.lightoncommand; + +import command.remote.command; +import command.remote.light; + +class LightOnCommand : Command +{ + Light light; + + this(Light light) + { + this.light = light; + } + + override void execute() + { + light.on(); + } +} diff --git a/command/remote/nocommand.d b/command/remote/nocommand.d new file mode 100644 index 0000000..85b138d --- /dev/null +++ b/command/remote/nocommand.d @@ -0,0 +1,8 @@ +module command.remote.nocommand; + +import command.remote.command; + +class NoCommand : Command +{ + override void execute() {} +} diff --git a/command/remote/remotecontrol.d b/command/remote/remotecontrol.d new file mode 100644 index 0000000..b842b2c --- /dev/null +++ b/command/remote/remotecontrol.d @@ -0,0 +1,54 @@ +module command.remote.remotecontrol; + +import command.remote.command; +import command.remote.nocommand; +import std.conv : to; +import std.stdio : writeln; +import std.algorithm.mutation : fill; +import std.array : split, back; +import std.format; + +class RemoteControl +{ + Command[] onCommands; + Command[] offCommands; + + this() + { + onCommands = new Command[7]; + offCommands = new Command[7]; + Command noCommand = new NoCommand(); + fill(onCommands, noCommand); + fill(offCommands, noCommand); + } + + void setCommand(int slot, Command onCommand, Command offCommand) + { + onCommands[slot] = onCommand; + offCommands[slot] = offCommand; + } + + void onButtonWasPressed(int slot) + { + onCommands[slot].execute(); + } + + void offButtonWasPressed(int slot) + { + offCommands[slot].execute(); + } + + override string toString() const + { + string s = "\n------ Remote Control -------\n"; + for (int i = 0; i < 7; ++i) + { + s ~= "[slot " ~ i.to!string ~ "] " + ~ format("%22s", (cast(Object)onCommands[i]).classinfo.name.split(".").back()) + ~ format("%23s", (cast(Object)offCommands[i]).classinfo.name.split(".").back()) + ~ "\n"; + } + + return s; + } +} diff --git a/command/remote/stereo.d b/command/remote/stereo.d new file mode 100644 index 0000000..65f32f8 --- /dev/null +++ b/command/remote/stereo.d @@ -0,0 +1,44 @@ +module command.remote.stereo; + +import std.stdio : writeln; +import std.conv : to; + +class Stereo +{ + string location; + + this(string location) + { + this.location = location; + } + + void on() + { + writeln(location ~ " stereo is on"); + } + + void off() + { + writeln(location ~ " stereo is off"); + } + + void setCD() + { + writeln(location ~ " stereo is set for CD input"); + } + + void setDVD() + { + writeln(location ~ " stereo is set for DVD input"); + } + + void setRadio() + { + writeln(location ~ " stereo is set for Radio"); + } + + void setVolume(int volume) + { + writeln(location ~ " stereo volume set to " ~ volume.to!string); + } +} diff --git a/command/remote/stereooffcommand.d b/command/remote/stereooffcommand.d new file mode 100644 index 0000000..ed9dcf4 --- /dev/null +++ b/command/remote/stereooffcommand.d @@ -0,0 +1,19 @@ +module command.remote.stereooffcommand; + +import command.remote.command; +import command.remote.stereo; + +class StereoOffCommand : Command +{ + Stereo stereo; + + this(Stereo stereo) + { + this.stereo = stereo; + } + + void execute() + { + stereo.off(); + } +} diff --git a/command/remote/stereoonwithcdcommand.d b/command/remote/stereoonwithcdcommand.d new file mode 100644 index 0000000..8b8c87a --- /dev/null +++ b/command/remote/stereoonwithcdcommand.d @@ -0,0 +1,21 @@ +module command.remote.stereoonwithcdcommand; + +import command.remote.command; +import command.remote.stereo; + +class StereoOnWithCDCommand : Command +{ + Stereo stereo; + + this(Stereo stereo) + { + this.stereo = stereo; + } + + void execute() + { + stereo.on(); + stereo.setCD(); + stereo.setVolume(11); + } +} diff --git a/command/remoteundo/app.d b/command/remoteundo/app.d new file mode 100644 index 0000000..fed0b16 --- /dev/null +++ b/command/remoteundo/app.d @@ -0,0 +1,52 @@ +module command.remoteundo.app; + +import command.remoteundo.remotecontrol; +import command.remoteundo.lightoncommand; +import command.remoteundo.lightoffcommand; +import command.remoteundo.light; +import command.remoteundo.ceilingfan; +import command.remoteundo.ceilingfanoffcommand; +import command.remoteundo.ceilingfanoncommand; +import command.remoteundo.garagedoorupcommand; +import command.remoteundo.garagedoordowncommand; +import command.remoteundo.garagedoor; +import command.remoteundo.stereoonwithcdcommand; +import command.remoteundo.stereo; +import command.remoteundo.stereooffcommand; +import std.stdio : writeln; + +void main() +{ + auto remoteControl = new RemoteControl(); + + auto livingRoomLight = new Light("Living Room"); + // auto kitchenLight = new Light("Kitchen"); + // auto ceilingFan = new CeilingFan("Living Room"); + // auto garageDoor = new GarageDoor("Garage"); + // auto stereo = new Stereo("Living Room"); + + remoteControl.setCommand(0, new LightOnCommand(livingRoomLight), new LightOffCommand(livingRoomLight)); + // remoteControl.setCommand(1, new LightOnCommand(kitchenLight), new LightOffCommand(kitchenLight)); + // remoteControl.setCommand(2, new CeilingFanOnCommand(ceilingFan), new CeilingFanOffCommand(ceilingFan)); + // remoteControl.setCommand(3, new StereoOnWithCDCommand(stereo), new StereoOffCommand(stereo)); + // remoteControl.setCommand(4, new GarageDoorUpCommand(garageDoor), new GarageDoorDownCommand(garageDoor)); + + // writeln(remoteControl); + + remoteControl.onButtonWasPushed(0); + remoteControl.offButtonWasPushed(0); + writeln(remoteControl); + remoteControl.undoButtonWasPushed(); + remoteControl.offButtonWasPushed(0); + remoteControl.onButtonWasPushed(0); + writeln(remoteControl); + remoteControl.undoButtonWasPushed(); + // remoteControl.onButtonWasPushed(1); + // remoteControl.offButtonWasPushed(1); + // remoteControl.onButtonWasPushed(2); + // remoteControl.offButtonWasPushed(2); + // remoteControl.onButtonWasPushed(3); + // remoteControl.offButtonWasPushed(3); + // remoteControl.onButtonWasPushed(4); + // remoteControl.offButtonWasPushed(4); +} diff --git a/command/remoteundo/ceilingfan.d b/command/remoteundo/ceilingfan.d new file mode 100644 index 0000000..99c5607 --- /dev/null +++ b/command/remoteundo/ceilingfan.d @@ -0,0 +1,48 @@ +module command.remoteundo.ceilingfan; + +import std.stdio : writeln; + +class CeilingFan +{ + private string location; + private int level; + + static int HIGH = 2; + static int MEDIUM = 1; + static int LOW = 0; + + this(string location) + { + this.location = location; + } + + void high() + { + level = HIGH; + writeln(location ~ " ceiling fan is on high"); + + } + + void medium() + { + level = MEDIUM; + writeln(location ~ " ceiling fan is on medium"); + } + + void low() + { + level = LOW; + writeln(location ~ " ceiling fan is on low"); + } + + void off() + { + level = 0; + writeln(location ~ " ceiling fan is off"); + } + + int getSpeed() + { + return level; + } +} diff --git a/command/remoteundo/ceilingfanoffcommand.d b/command/remoteundo/ceilingfanoffcommand.d new file mode 100644 index 0000000..dad5174 --- /dev/null +++ b/command/remoteundo/ceilingfanoffcommand.d @@ -0,0 +1,24 @@ +module command.remoteundo.ceilingfanoffcommand; + +import command.remoteundo.command; +import command.remoteundo.ceilingfan; + +class CeilingFanOffCommand : Command +{ + CeilingFan ceilingFan; + + this(CeilingFan ceilingFan) + { + this.ceilingFan = ceilingFan; + } + + void execute() + { + ceilingFan.off(); + } + + void undo() + { + ceilingFan.high(); + } +} diff --git a/command/remoteundo/ceilingfanoncommand.d b/command/remoteundo/ceilingfanoncommand.d new file mode 100644 index 0000000..8f2b683 --- /dev/null +++ b/command/remoteundo/ceilingfanoncommand.d @@ -0,0 +1,24 @@ +module command.remoteundo.ceilingfanoncommand; + +import command.remoteundo.command; +import command.remoteundo.ceilingfan; + +class CeilingFanOnCommand : Command +{ + CeilingFan ceilingFan; + + this(CeilingFan ceilingFan) + { + this.ceilingFan = ceilingFan; + } + + void execute() + { + ceilingFan.high(); + } + + void undo() + { + ceilingFan.off(); + } +} diff --git a/command/remoteundo/command.d b/command/remoteundo/command.d new file mode 100644 index 0000000..fe1bba1 --- /dev/null +++ b/command/remoteundo/command.d @@ -0,0 +1,7 @@ +module command.remoteundo.command; + +interface Command +{ + void execute(); + void undo(); +} diff --git a/command/remoteundo/garagedoor.d b/command/remoteundo/garagedoor.d new file mode 100644 index 0000000..720f224 --- /dev/null +++ b/command/remoteundo/garagedoor.d @@ -0,0 +1,38 @@ +module command.remoteundo.garagedoor; + +import std.stdio : writeln; + +class GarageDoor +{ + private string location; + + this(string location) + { + this.location = location; + } + + void up() + { + writeln(location ~ " garage Door is Up"); + } + + void down() + { + writeln(location ~ " garage Door is Down"); + } + + void stop() + { + writeln(location ~ " garage Door is Stopped"); + } + + void lightOn() + { + writeln(location ~ " garage light is on"); + } + + void lightOff() + { + writeln(location ~ " garage light is off"); + } +} diff --git a/command/remoteundo/garagedoordowncommand.d b/command/remoteundo/garagedoordowncommand.d new file mode 100644 index 0000000..d9d3c24 --- /dev/null +++ b/command/remoteundo/garagedoordowncommand.d @@ -0,0 +1,24 @@ +module command.remoteundo.garagedoordowncommand; + +import command.remoteundo.command; +import command.remoteundo.garagedoor; + +class GarageDoorDownCommand : Command +{ + GarageDoor garageDoor; + + this(GarageDoor garageDoor) + { + this.garageDoor = garageDoor; + } + + void execute() + { + garageDoor.down(); + } + + void undo() + { + garageDoor.up(); + } +} diff --git a/command/remoteundo/garagedoorupcommand.d b/command/remoteundo/garagedoorupcommand.d new file mode 100644 index 0000000..70cdb0d --- /dev/null +++ b/command/remoteundo/garagedoorupcommand.d @@ -0,0 +1,24 @@ +module command.remoteundo.garagedoorupcommand; + +import command.remoteundo.command; +import command.remoteundo.garagedoor; + +class GarageDoorUpCommand : Command +{ + GarageDoor garageDoor; + + this(GarageDoor garageDoor) + { + this.garageDoor = garageDoor; + } + + void execute() + { + garageDoor.up(); + } + + void undo() + { + garageDoor.down(); + } +} diff --git a/command/remoteundo/light.d b/command/remoteundo/light.d new file mode 100644 index 0000000..ad6f09b --- /dev/null +++ b/command/remoteundo/light.d @@ -0,0 +1,23 @@ +module command.remoteundo.light; + +import std.stdio : writeln; + +class Light +{ + private string location; + + this(string location) + { + this.location = location; + } + + void on() + { + writeln(location ~ " light is On"); + } + + void off() + { + writeln(location ~ " light is Off"); + } +} diff --git a/command/remoteundo/lightoffcommand.d b/command/remoteundo/lightoffcommand.d new file mode 100644 index 0000000..638a7e8 --- /dev/null +++ b/command/remoteundo/lightoffcommand.d @@ -0,0 +1,24 @@ +module command.remoteundo.lightoffcommand; + +import command.remoteundo.command; +import command.remoteundo.light; + +class LightOffCommand : Command +{ + Light light; + + this(Light light) + { + this.light = light; + } + + void execute() + { + light.off(); + } + + void undo() + { + light.on(); + } +} diff --git a/command/remoteundo/lightoncommand.d b/command/remoteundo/lightoncommand.d new file mode 100644 index 0000000..1a94203 --- /dev/null +++ b/command/remoteundo/lightoncommand.d @@ -0,0 +1,24 @@ +module command.remoteundo.lightoncommand; + +import command.remoteundo.command; +import command.remoteundo.light; + +class LightOnCommand : Command +{ + Light light; + + this(Light light) + { + this.light = light; + } + + void execute() + { + light.on(); + } + + void undo() + { + light.off(); + } +} diff --git a/command/remoteundo/nocommand.d b/command/remoteundo/nocommand.d new file mode 100644 index 0000000..e81c3fd --- /dev/null +++ b/command/remoteundo/nocommand.d @@ -0,0 +1,9 @@ +module command.remoteundo.nocommand; + +import command.remoteundo.command; + +class NoCommand : Command +{ + void execute() {} + void undo() {} +} diff --git a/command/remoteundo/remotecontrol.d b/command/remoteundo/remotecontrol.d new file mode 100644 index 0000000..7cba07a --- /dev/null +++ b/command/remoteundo/remotecontrol.d @@ -0,0 +1,63 @@ +module command.remoteundo.remotecontrol; + +import command.remoteundo.command; +import command.remoteundo.nocommand; +import std.conv : to; +import std.stdio : writeln; +import std.algorithm.mutation : fill; +import std.array : split, back; +import std.format; + +class RemoteControl +{ + Command[] onCommands; + Command[] offCommands; + Command undoCommand; + + this() + { + onCommands = new Command[7]; + offCommands = new Command[7]; + Command noCommand = new NoCommand(); + fill(onCommands, noCommand); + fill(offCommands, noCommand); + undoCommand = noCommand; + } + + void setCommand(int slot, Command onCommand, Command offCommand) + { + onCommands[slot] = onCommand; + offCommands[slot] = offCommand; + } + + void onButtonWasPushed(int slot) + { + onCommands[slot].execute(); + undoCommand = onCommands[slot]; + } + + void offButtonWasPushed(int slot) + { + offCommands[slot].execute(); + undoCommand = offCommands[slot]; + } + + void undoButtonWasPushed() + { + undoCommand.undo(); + } + + override string toString() const + { + string s = "\n------ Remote Control -------\n"; + for (int i = 0; i < 7; ++i) + { + s ~= "[slot " ~ i.to!string ~ "] " + ~ format("%22s", (cast(Object)onCommands[i]).classinfo.name.split(".").back()) + ~ format("%23s", (cast(Object)offCommands[i]).classinfo.name.split(".").back()) + ~ "\n"; + } + + return s ~ "[undo] " ~ (cast(Object)undoCommand).classinfo.name.split(".").back() ~ "\n"; + } +} diff --git a/command/remoteundo/stereo.d b/command/remoteundo/stereo.d new file mode 100644 index 0000000..167efb9 --- /dev/null +++ b/command/remoteundo/stereo.d @@ -0,0 +1,44 @@ +module command.remoteundo.stereo; + +import std.stdio : writeln; +import std.conv : to; + +class Stereo +{ + string location; + + this(string location) + { + this.location = location; + } + + void on() + { + writeln(location ~ " stereo is on"); + } + + void off() + { + writeln(location ~ " stereo is off"); + } + + void setCD() + { + writeln(location ~ " stereo is set for CD input"); + } + + void setDVD() + { + writeln(location ~ " stereo is set for DVD input"); + } + + void setRadio() + { + writeln(location ~ " stereo is set for Radio"); + } + + void setVolume(int volume) + { + writeln(location ~ " stereo volume set to " ~ volume.to!string); + } +} diff --git a/command/remoteundo/stereooffcommand.d b/command/remoteundo/stereooffcommand.d new file mode 100644 index 0000000..5f79e61 --- /dev/null +++ b/command/remoteundo/stereooffcommand.d @@ -0,0 +1,26 @@ +module command.remoteundo.stereooffcommand; + +import command.remoteundo.command; +import command.remoteundo.stereo; + +class StereoOffCommand : Command +{ + Stereo stereo; + + this(Stereo stereo) + { + this.stereo = stereo; + } + + void execute() + { + stereo.off(); + } + + void undo() + { + stereo.on(); + stereo.setCD(); + stereo.setVolume(11); + } +} diff --git a/command/remoteundo/stereoonwithcdcommand.d b/command/remoteundo/stereoonwithcdcommand.d new file mode 100644 index 0000000..222899c --- /dev/null +++ b/command/remoteundo/stereoonwithcdcommand.d @@ -0,0 +1,26 @@ +module command.remoteundo.stereoonwithcdcommand; + +import command.remoteundo.command; +import command.remoteundo.stereo; + +class StereoOnWithCDCommand : Command +{ + Stereo stereo; + + this(Stereo stereo) + { + this.stereo = stereo; + } + + void execute() + { + stereo.on(); + stereo.setCD(); + stereo.setVolume(11); + } + + void undo() + { + stereo.off(); + } +} diff --git a/command/remoteundostatus/app.d b/command/remoteundostatus/app.d new file mode 100644 index 0000000..3c9b6fa --- /dev/null +++ b/command/remoteundostatus/app.d @@ -0,0 +1,36 @@ +module command.remoteundostatus.app; + +import command.remoteundostatus.remotecontrol; +import command.remoteundostatus.lightoncommand; +import command.remoteundostatus.lightoffcommand; +import command.remoteundostatus.light; +import command.remoteundostatus.ceilingfan; +import command.remoteundostatus.ceilingfanoffcommand; +import command.remoteundostatus.ceilingfanhighcommand; +import command.remoteundostatus.ceilingfanmediumcommand; +import command.remoteundostatus.ceilingfanlowcommand; +import command.remoteundostatus.garagedoorupcommand; +import command.remoteundostatus.garagedoordowncommand; +import command.remoteundostatus.garagedoor; +import command.remoteundostatus.stereoonwithcdcommand; +import command.remoteundostatus.stereo; +import command.remoteundostatus.stereooffcommand; +import std.stdio : writeln; + +void main() +{ + auto remoteControl = new RemoteControl(); + + auto ceilingFan = new CeilingFan("Living Room"); + + remoteControl.setCommand(0, new CeilingFanMediumCommand(ceilingFan), new CeilingFanOffCommand(ceilingFan)); + remoteControl.setCommand(1, new CeilingFanHighCommand(ceilingFan), new CeilingFanOffCommand(ceilingFan)); + + remoteControl.onButtonWasPushed(0); + remoteControl.offButtonWasPushed(0); + writeln(remoteControl); + remoteControl.undoButtonWasPushed(); + remoteControl.onButtonWasPushed(1); + writeln(remoteControl); + remoteControl.undoButtonWasPushed(); +} \ No newline at end of file diff --git a/command/remoteundostatus/ceilingfan.d b/command/remoteundostatus/ceilingfan.d new file mode 100644 index 0000000..fc2e9b7 --- /dev/null +++ b/command/remoteundostatus/ceilingfan.d @@ -0,0 +1,49 @@ +module command.remoteundostatus.ceilingfan; + +import std.stdio : writeln; + +class CeilingFan +{ + private string location; + private int speed; + + static const int HIGH = 3; + static const int MEDIUM = 2; + static const int LOW = 1; + static const int OFF = 0; + + this(string location) + { + this.location = location; + } + + void high() + { + speed = HIGH; + writeln(location ~ " ceiling fan is on high"); + + } + + void medium() + { + speed = MEDIUM; + writeln(location ~ " ceiling fan is on medium"); + } + + void low() + { + speed = LOW; + writeln(location ~ " ceiling fan is on low"); + } + + void off() + { + speed = OFF; + writeln(location ~ " ceiling fan is off"); + } + + int getSpeed() + { + return speed; + } +} diff --git a/command/remoteundostatus/ceilingfanhighcommand.d b/command/remoteundostatus/ceilingfanhighcommand.d new file mode 100644 index 0000000..c591fe4 --- /dev/null +++ b/command/remoteundostatus/ceilingfanhighcommand.d @@ -0,0 +1,41 @@ +module command.remoteundostatus.ceilingfanhighcommand; + +import command.remoteundostatus.command; +import command.remoteundostatus.ceilingfan; + +class CeilingFanHighCommand : Command +{ + CeilingFan ceilingFan; + int prevSpeed; + + this(CeilingFan ceilingFan) + { + this.ceilingFan = ceilingFan; + } + + void execute() + { + prevSpeed = ceilingFan.getSpeed(); + ceilingFan.high(); + } + + void undo() + { + switch (prevSpeed) + { + case CeilingFan.HIGH: + ceilingFan.high(); + break; + case CeilingFan.MEDIUM: + ceilingFan.medium(); + break; + case CeilingFan.LOW: + ceilingFan.low(); + break; + case CeilingFan.OFF: + ceilingFan.off(); + break; + default: break; + } + } +} diff --git a/command/remoteundostatus/ceilingfanlowcommand.d b/command/remoteundostatus/ceilingfanlowcommand.d new file mode 100644 index 0000000..a815785 --- /dev/null +++ b/command/remoteundostatus/ceilingfanlowcommand.d @@ -0,0 +1,41 @@ +module command.remoteundostatus.ceilingfanlowcommand; + +import command.remoteundostatus.command; +import command.remoteundostatus.ceilingfan; + +class CeilingFanLowCommand : Command +{ + CeilingFan ceilingFan; + int prevSpeed; + + this(CeilingFan ceilingFan) + { + this.ceilingFan = ceilingFan; + } + + void execute() + { + prevSpeed = ceilingFan.getSpeed(); + ceilingFan.low(); + } + + void undo() + { + switch (prevSpeed) + { + case CeilingFan.HIGH: + ceilingFan.high(); + break; + case CeilingFan.MEDIUM: + ceilingFan.medium(); + break; + case CeilingFan.LOW: + ceilingFan.low(); + break; + case CeilingFan.OFF: + ceilingFan.off(); + break; + default: break; + } + } +} diff --git a/command/remoteundostatus/ceilingfanmediumcommand.d b/command/remoteundostatus/ceilingfanmediumcommand.d new file mode 100644 index 0000000..de974b0 --- /dev/null +++ b/command/remoteundostatus/ceilingfanmediumcommand.d @@ -0,0 +1,41 @@ +module command.remoteundostatus.ceilingfanmediumcommand; + +import command.remoteundostatus.command; +import command.remoteundostatus.ceilingfan; + +class CeilingFanMediumCommand : Command +{ + CeilingFan ceilingFan; + int prevSpeed; + + this(CeilingFan ceilingFan) + { + this.ceilingFan = ceilingFan; + } + + void execute() + { + prevSpeed = ceilingFan.getSpeed(); + ceilingFan.medium(); + } + + void undo() + { + switch (prevSpeed) + { + case CeilingFan.HIGH: + ceilingFan.high(); + break; + case CeilingFan.MEDIUM: + ceilingFan.medium(); + break; + case CeilingFan.LOW: + ceilingFan.low(); + break; + case CeilingFan.OFF: + ceilingFan.off(); + break; + default: break; + } + } +} diff --git a/command/remoteundostatus/ceilingfanoffcommand.d b/command/remoteundostatus/ceilingfanoffcommand.d new file mode 100644 index 0000000..3e5e174 --- /dev/null +++ b/command/remoteundostatus/ceilingfanoffcommand.d @@ -0,0 +1,41 @@ +module command.remoteundostatus.ceilingfanoffcommand; + +import command.remoteundostatus.command; +import command.remoteundostatus.ceilingfan; + +class CeilingFanOffCommand : Command +{ + CeilingFan ceilingFan; + int prevSpeed; + + this(CeilingFan ceilingFan) + { + this.ceilingFan = ceilingFan; + } + + void execute() + { + prevSpeed = ceilingFan.getSpeed(); + ceilingFan.off(); + } + + void undo() + { + switch (prevSpeed) + { + case CeilingFan.HIGH: + ceilingFan.high(); + break; + case CeilingFan.MEDIUM: + ceilingFan.medium(); + break; + case CeilingFan.LOW: + ceilingFan.low(); + break; + case CeilingFan.OFF: + ceilingFan.off(); + break; + default: break; + } + } +} diff --git a/command/remoteundostatus/command.d b/command/remoteundostatus/command.d new file mode 100644 index 0000000..a1945ae --- /dev/null +++ b/command/remoteundostatus/command.d @@ -0,0 +1,7 @@ +module command.remoteundostatus.command; + +interface Command +{ + void execute(); + void undo(); +} diff --git a/command/remoteundostatus/garagedoor.d b/command/remoteundostatus/garagedoor.d new file mode 100644 index 0000000..1bf9ac5 --- /dev/null +++ b/command/remoteundostatus/garagedoor.d @@ -0,0 +1,38 @@ +module command.remoteundostatus.garagedoor; + +import std.stdio : writeln; + +class GarageDoor +{ + private string location; + + this(string location) + { + this.location = location; + } + + void up() + { + writeln(location ~ " garage Door is Up"); + } + + void down() + { + writeln(location ~ " garage Door is Down"); + } + + void stop() + { + writeln(location ~ " garage Door is Stopped"); + } + + void lightOn() + { + writeln(location ~ " garage light is on"); + } + + void lightOff() + { + writeln(location ~ " garage light is off"); + } +} diff --git a/command/remoteundostatus/garagedoordowncommand.d b/command/remoteundostatus/garagedoordowncommand.d new file mode 100644 index 0000000..c47de33 --- /dev/null +++ b/command/remoteundostatus/garagedoordowncommand.d @@ -0,0 +1,24 @@ +module command.remoteundostatus.garagedoordowncommand; + +import command.remoteundostatus.command; +import command.remoteundostatus.garagedoor; + +class GarageDoorDownCommand : Command +{ + GarageDoor garageDoor; + + this(GarageDoor garageDoor) + { + this.garageDoor = garageDoor; + } + + void execute() + { + garageDoor.down(); + } + + void undo() + { + garageDoor.up(); + } +} diff --git a/command/remoteundostatus/garagedoorupcommand.d b/command/remoteundostatus/garagedoorupcommand.d new file mode 100644 index 0000000..5f865bb --- /dev/null +++ b/command/remoteundostatus/garagedoorupcommand.d @@ -0,0 +1,24 @@ +module command.remoteundostatus.garagedoorupcommand; + +import command.remoteundostatus.command; +import command.remoteundostatus.garagedoor; + +class GarageDoorUpCommand : Command +{ + GarageDoor garageDoor; + + this(GarageDoor garageDoor) + { + this.garageDoor = garageDoor; + } + + void execute() + { + garageDoor.up(); + } + + void undo() + { + garageDoor.down(); + } +} diff --git a/command/remoteundostatus/light.d b/command/remoteundostatus/light.d new file mode 100644 index 0000000..aa0cf4e --- /dev/null +++ b/command/remoteundostatus/light.d @@ -0,0 +1,23 @@ +module command.remoteundostatus.light; + +import std.stdio : writeln; + +class Light +{ + private string location; + + this(string location) + { + this.location = location; + } + + void on() + { + writeln(location ~ " light is On"); + } + + void off() + { + writeln(location ~ " light is Off"); + } +} diff --git a/command/remoteundostatus/lightoffcommand.d b/command/remoteundostatus/lightoffcommand.d new file mode 100644 index 0000000..c66f98b --- /dev/null +++ b/command/remoteundostatus/lightoffcommand.d @@ -0,0 +1,24 @@ +module command.remoteundostatus.lightoffcommand; + +import command.remoteundostatus.command; +import command.remoteundostatus.light; + +class LightOffCommand : Command +{ + Light light; + + this(Light light) + { + this.light = light; + } + + void execute() + { + light.off(); + } + + void undo() + { + light.on(); + } +} diff --git a/command/remoteundostatus/lightoncommand.d b/command/remoteundostatus/lightoncommand.d new file mode 100644 index 0000000..24619ea --- /dev/null +++ b/command/remoteundostatus/lightoncommand.d @@ -0,0 +1,24 @@ +module command.remoteundostatus.lightoncommand; + +import command.remoteundostatus.command; +import command.remoteundostatus.light; + +class LightOnCommand : Command +{ + Light light; + + this(Light light) + { + this.light = light; + } + + void execute() + { + light.on(); + } + + void undo() + { + light.off(); + } +} diff --git a/command/remoteundostatus/nocommand.d b/command/remoteundostatus/nocommand.d new file mode 100644 index 0000000..8f81974 --- /dev/null +++ b/command/remoteundostatus/nocommand.d @@ -0,0 +1,9 @@ +module command.remoteundostatus.nocommand; + +import command.remoteundostatus.command; + +class NoCommand : Command +{ + void execute() {} + void undo() {} +} diff --git a/command/remoteundostatus/remotecontrol.d b/command/remoteundostatus/remotecontrol.d new file mode 100644 index 0000000..2366274 --- /dev/null +++ b/command/remoteundostatus/remotecontrol.d @@ -0,0 +1,63 @@ +module command.remoteundostatus.remotecontrol; + +import command.remoteundostatus.command; +import command.remoteundostatus.nocommand; +import std.conv : to; +import std.stdio : writeln; +import std.algorithm.mutation : fill; +import std.array : split, back; +import std.format; + +class RemoteControl +{ + Command[] onCommands; + Command[] offCommands; + Command undoCommand; + + this() + { + onCommands = new Command[7]; + offCommands = new Command[7]; + Command noCommand = new NoCommand(); + fill(onCommands, noCommand); + fill(offCommands, noCommand); + undoCommand = noCommand; + } + + void setCommand(int slot, Command onCommand, Command offCommand) + { + onCommands[slot] = onCommand; + offCommands[slot] = offCommand; + } + + void onButtonWasPushed(int slot) + { + onCommands[slot].execute(); + undoCommand = onCommands[slot]; + } + + void offButtonWasPushed(int slot) + { + offCommands[slot].execute(); + undoCommand = offCommands[slot]; + } + + void undoButtonWasPushed() + { + undoCommand.undo(); + } + + override string toString() const + { + string s = "\n------ Remote Control -------\n"; + for (int i = 0; i < 7; ++i) + { + s ~= "[slot " ~ i.to!string ~ "] " + ~ format("%23s", (cast(Object)onCommands[i]).classinfo.name.split(".").back()) + ~ format("%23s", (cast(Object)offCommands[i]).classinfo.name.split(".").back()) + ~ "\n"; + } + + return s ~ "[undo] " ~ (cast(Object)undoCommand).classinfo.name.split(".").back() ~ "\n"; + } +} diff --git a/command/remoteundostatus/stereo.d b/command/remoteundostatus/stereo.d new file mode 100644 index 0000000..09d7cf9 --- /dev/null +++ b/command/remoteundostatus/stereo.d @@ -0,0 +1,44 @@ +module command.remoteundostatus.stereo; + +import std.stdio : writeln; +import std.conv : to; + +class Stereo +{ + string location; + + this(string location) + { + this.location = location; + } + + void on() + { + writeln(location ~ " stereo is on"); + } + + void off() + { + writeln(location ~ " stereo is off"); + } + + void setCD() + { + writeln(location ~ " stereo is set for CD input"); + } + + void setDVD() + { + writeln(location ~ " stereo is set for DVD input"); + } + + void setRadio() + { + writeln(location ~ " stereo is set for Radio"); + } + + void setVolume(int volume) + { + writeln(location ~ " stereo volume set to " ~ volume.to!string); + } +} diff --git a/command/remoteundostatus/stereooffcommand.d b/command/remoteundostatus/stereooffcommand.d new file mode 100644 index 0000000..b1a5fed --- /dev/null +++ b/command/remoteundostatus/stereooffcommand.d @@ -0,0 +1,26 @@ +module command.remoteundostatus.stereooffcommand; + +import command.remoteundostatus.command; +import command.remoteundostatus.stereo; + +class StereoOffCommand : Command +{ + Stereo stereo; + + this(Stereo stereo) + { + this.stereo = stereo; + } + + void execute() + { + stereo.off(); + } + + void undo() + { + stereo.on(); + stereo.setCD(); + stereo.setVolume(11); + } +} diff --git a/command/remoteundostatus/stereoonwithcdcommand.d b/command/remoteundostatus/stereoonwithcdcommand.d new file mode 100644 index 0000000..b69353b --- /dev/null +++ b/command/remoteundostatus/stereoonwithcdcommand.d @@ -0,0 +1,26 @@ +module command.remoteundostatus.stereoonwithcdcommand; + +import command.remoteundostatus.command; +import command.remoteundostatus.stereo; + +class StereoOnWithCDCommand : Command +{ + Stereo stereo; + + this(Stereo stereo) + { + this.stereo = stereo; + } + + void execute() + { + stereo.on(); + stereo.setCD(); + stereo.setVolume(11); + } + + void undo() + { + stereo.off(); + } +} diff --git a/command/remoteundostatusmacro/app.d b/command/remoteundostatusmacro/app.d new file mode 100644 index 0000000..8940c5e --- /dev/null +++ b/command/remoteundostatusmacro/app.d @@ -0,0 +1,54 @@ +module command.remoteundostatusmacro.app; + +import command.remoteundostatusmacro.remotecontrol; +import command.remoteundostatusmacro.lightoncommand; +import command.remoteundostatusmacro.lightoffcommand; +import command.remoteundostatusmacro.light; +import command.remoteundostatusmacro.tv; +import command.remoteundostatusmacro.tvoffcommand; +import command.remoteundostatusmacro.tvoncommand; +import command.remoteundostatusmacro.hottub; +import command.remoteundostatusmacro.hottuboffcommand; +import command.remoteundostatusmacro.hottuboncommand; +import command.remoteundostatusmacro.stereoonwithcdcommand; +import command.remoteundostatusmacro.stereo; +import command.remoteundostatusmacro.stereooffcommand; +import command.remoteundostatusmacro.command; +import command.remoteundostatusmacro.macrocommand; +import std.stdio : writeln; + +void main() +{ + auto remoteControl = new RemoteControl(); + + auto light = new Light("Living Room"); + auto tv = new TV("Living Room"); + auto stereo = new Stereo("Living Room"); + auto hottub = new Hottub(); + + Command[] partyOn = cast(Command[])[ + new LightOnCommand(light), + new StereoOnWithCDCommand(stereo), + new TVOnCommand(tv), + new HottubOnCommand(hottub) + ]; + Command[] partyOff = cast(Command[])[ + new LightOffCommand(light), + new StereoOffCommand(stereo), + new TVOffCommand(tv), + new HottubOffCommand(hottub) + ]; + + remoteControl.setCommand(0, new MacroCommand(partyOn), new MacroCommand(partyOff)); + + writeln(remoteControl); + writeln("--- Pushing Macro On ---"); + remoteControl.onButtonWasPushed(0); + writeln("--- Pushing Macro Off ---"); + remoteControl.offButtonWasPushed(0); + writeln(remoteControl); + remoteControl.undoButtonWasPushed(); + writeln(remoteControl); + remoteControl.onButtonWasPushed(0); + writeln(remoteControl); +} \ No newline at end of file diff --git a/command/remoteundostatusmacro/command.d b/command/remoteundostatusmacro/command.d new file mode 100644 index 0000000..350ed3d --- /dev/null +++ b/command/remoteundostatusmacro/command.d @@ -0,0 +1,7 @@ +module command.remoteundostatusmacro.command; + +interface Command +{ + void execute(); + void undo(); +} diff --git a/command/remoteundostatusmacro/hottub.d b/command/remoteundostatusmacro/hottub.d new file mode 100644 index 0000000..833a90a --- /dev/null +++ b/command/remoteundostatusmacro/hottub.d @@ -0,0 +1,58 @@ +module command.remoteundostatusmacro.hottub; + +import std.stdio : writeln; +import std.conv : to; + +class Hottub +{ + private bool isOn; + private int temperature; + + void on() + { + isOn = true; + } + + void off() + { + isOn = false; + } + + void circulate() + { + if (isOn) + { + writeln("Hottub is bubbling!"); + } + } + + void jetsOn() + { + if (isOn) + { + writeln("Hottub jets are on"); + } + } + + void jetsOff() + { + if (isOn) + { + writeln("Hottub jets are off"); + } + } + + void setTemperature(int temperature) + { + if (temperature > this.temperature) + { + writeln("Hottub is heating to a steaming " ~ temperature.to!string ~ " degrees"); + } + else + { + writeln("Hottub is cooling to " ~ temperature.to!string ~ " degrees"); + } + + this.temperature = temperature; + } +} diff --git a/command/remoteundostatusmacro/hottuboffcommand.d b/command/remoteundostatusmacro/hottuboffcommand.d new file mode 100644 index 0000000..b146284 --- /dev/null +++ b/command/remoteundostatusmacro/hottuboffcommand.d @@ -0,0 +1,25 @@ +module command.remoteundostatusmacro.hottuboffcommand; + +import command.remoteundostatusmacro.command; +import command.remoteundostatusmacro.hottub; + +class HottubOffCommand : Command +{ + Hottub hottub; + + this(Hottub hottub) + { + this.hottub = hottub; + } + + void execute() + { + hottub.setTemperature(98); + hottub.off(); + } + + void undo() + { + hottub.on(); + } +} diff --git a/command/remoteundostatusmacro/hottuboncommand.d b/command/remoteundostatusmacro/hottuboncommand.d new file mode 100644 index 0000000..d50a2ec --- /dev/null +++ b/command/remoteundostatusmacro/hottuboncommand.d @@ -0,0 +1,26 @@ +module command.remoteundostatusmacro.hottuboncommand; + +import command.remoteundostatusmacro.command; +import command.remoteundostatusmacro.hottub; + +class HottubOnCommand : Command +{ + Hottub hottub; + + this(Hottub hottub) + { + this.hottub = hottub; + } + + void execute() + { + hottub.on(); + hottub.setTemperature(104); + hottub.circulate(); + } + + void undo() + { + hottub.off(); + } +} diff --git a/command/remoteundostatusmacro/light.d b/command/remoteundostatusmacro/light.d new file mode 100644 index 0000000..38d12c3 --- /dev/null +++ b/command/remoteundostatusmacro/light.d @@ -0,0 +1,23 @@ +module command.remoteundostatusmacro.light; + +import std.stdio : writeln; + +class Light +{ + private string location; + + this(string location) + { + this.location = location; + } + + void on() + { + writeln(location ~ " light is On"); + } + + void off() + { + writeln(location ~ " light is Off"); + } +} diff --git a/command/remoteundostatusmacro/lightoffcommand.d b/command/remoteundostatusmacro/lightoffcommand.d new file mode 100644 index 0000000..735dbf2 --- /dev/null +++ b/command/remoteundostatusmacro/lightoffcommand.d @@ -0,0 +1,24 @@ +module command.remoteundostatusmacro.lightoffcommand; + +import command.remoteundostatusmacro.command; +import command.remoteundostatusmacro.light; + +class LightOffCommand : Command +{ + Light light; + + this(Light light) + { + this.light = light; + } + + void execute() + { + light.off(); + } + + void undo() + { + light.on(); + } +} diff --git a/command/remoteundostatusmacro/lightoncommand.d b/command/remoteundostatusmacro/lightoncommand.d new file mode 100644 index 0000000..265dc71 --- /dev/null +++ b/command/remoteundostatusmacro/lightoncommand.d @@ -0,0 +1,24 @@ +module command.remoteundostatusmacro.lightoncommand; + +import command.remoteundostatusmacro.command; +import command.remoteundostatusmacro.light; + +class LightOnCommand : Command +{ + Light light; + + this(Light light) + { + this.light = light; + } + + void execute() + { + light.on(); + } + + void undo() + { + light.off(); + } +} diff --git a/command/remoteundostatusmacro/macrocommand.d b/command/remoteundostatusmacro/macrocommand.d new file mode 100644 index 0000000..b3b4315 --- /dev/null +++ b/command/remoteundostatusmacro/macrocommand.d @@ -0,0 +1,29 @@ +module command.remoteundostatusmacro.macrocommand; + +import command.remoteundostatusmacro.command; + +class MacroCommand : Command +{ + Command[] commands; + + this(Command[] commands) + { + this.commands = commands; + } + + void execute() + { + foreach (val; commands) + { + val.execute(); + } + } + + void undo() + { + foreach (val; commands) + { + val.undo(); + } + } +} diff --git a/command/remoteundostatusmacro/nocommand.d b/command/remoteundostatusmacro/nocommand.d new file mode 100644 index 0000000..54fc006 --- /dev/null +++ b/command/remoteundostatusmacro/nocommand.d @@ -0,0 +1,9 @@ +module command.remoteundostatusmacro.nocommand; + +import command.remoteundostatusmacro.command; + +class NoCommand : Command +{ + void execute() {} + void undo() {} +} diff --git a/command/remoteundostatusmacro/remotecontrol.d b/command/remoteundostatusmacro/remotecontrol.d new file mode 100644 index 0000000..d058881 --- /dev/null +++ b/command/remoteundostatusmacro/remotecontrol.d @@ -0,0 +1,63 @@ +module command.remoteundostatusmacro.remotecontrol; + +import command.remoteundostatusmacro.command; +import command.remoteundostatusmacro.nocommand; +import std.conv : to; +import std.stdio : writeln; +import std.algorithm.mutation : fill; +import std.array : split, back; +import std.format; + +class RemoteControl +{ + Command[] onCommands; + Command[] offCommands; + Command undoCommand; + + this() + { + onCommands = new Command[7]; + offCommands = new Command[7]; + Command noCommand = new NoCommand(); + fill(onCommands, noCommand); + fill(offCommands, noCommand); + undoCommand = noCommand; + } + + void setCommand(int slot, Command onCommand, Command offCommand) + { + onCommands[slot] = onCommand; + offCommands[slot] = offCommand; + } + + void onButtonWasPushed(int slot) + { + onCommands[slot].execute(); + undoCommand = onCommands[slot]; + } + + void offButtonWasPushed(int slot) + { + offCommands[slot].execute(); + undoCommand = offCommands[slot]; + } + + void undoButtonWasPushed() + { + undoCommand.undo(); + } + + override string toString() const + { + string s = "\n------ Remote Control -------\n"; + for (int i = 0; i < 7; ++i) + { + s ~= "[slot " ~ i.to!string ~ "] " + ~ format("%23s", (cast(Object)onCommands[i]).classinfo.name.split(".").back()) + ~ format("%23s", (cast(Object)offCommands[i]).classinfo.name.split(".").back()) + ~ "\n"; + } + + return s ~ "[undo] " ~ (cast(Object)undoCommand).classinfo.name.split(".").back() ~ "\n"; + } +} diff --git a/command/remoteundostatusmacro/stereo.d b/command/remoteundostatusmacro/stereo.d new file mode 100644 index 0000000..6493fdb --- /dev/null +++ b/command/remoteundostatusmacro/stereo.d @@ -0,0 +1,44 @@ +module command.remoteundostatusmacro.stereo; + +import std.stdio : writeln; +import std.conv : to; + +class Stereo +{ + string location; + + this(string location) + { + this.location = location; + } + + void on() + { + writeln(location ~ " stereo is on"); + } + + void off() + { + writeln(location ~ " stereo is off"); + } + + void setCD() + { + writeln(location ~ " stereo is set for CD input"); + } + + void setDVD() + { + writeln(location ~ " stereo is set for DVD input"); + } + + void setRadio() + { + writeln(location ~ " stereo is set for Radio"); + } + + void setVolume(int volume) + { + writeln(location ~ " stereo volume set to " ~ volume.to!string); + } +} diff --git a/command/remoteundostatusmacro/stereooffcommand.d b/command/remoteundostatusmacro/stereooffcommand.d new file mode 100644 index 0000000..cfeb708 --- /dev/null +++ b/command/remoteundostatusmacro/stereooffcommand.d @@ -0,0 +1,26 @@ +module command.remoteundostatusmacro.stereooffcommand; + +import command.remoteundostatusmacro.command; +import command.remoteundostatusmacro.stereo; + +class StereoOffCommand : Command +{ + Stereo stereo; + + this(Stereo stereo) + { + this.stereo = stereo; + } + + void execute() + { + stereo.off(); + } + + void undo() + { + stereo.on(); + stereo.setCD(); + stereo.setVolume(11); + } +} diff --git a/command/remoteundostatusmacro/stereoonwithcdcommand.d b/command/remoteundostatusmacro/stereoonwithcdcommand.d new file mode 100644 index 0000000..32171c9 --- /dev/null +++ b/command/remoteundostatusmacro/stereoonwithcdcommand.d @@ -0,0 +1,26 @@ +module command.remoteundostatusmacro.stereoonwithcdcommand; + +import command.remoteundostatusmacro.command; +import command.remoteundostatusmacro.stereo; + +class StereoOnWithCDCommand : Command +{ + Stereo stereo; + + this(Stereo stereo) + { + this.stereo = stereo; + } + + void execute() + { + stereo.on(); + stereo.setCD(); + stereo.setVolume(11); + } + + void undo() + { + stereo.off(); + } +} diff --git a/command/remoteundostatusmacro/tv.d b/command/remoteundostatusmacro/tv.d new file mode 100644 index 0000000..cee24af --- /dev/null +++ b/command/remoteundostatusmacro/tv.d @@ -0,0 +1,30 @@ +module command.remoteundostatusmacro.tv; + +import std.stdio : writeln; + +class TV +{ + private string location; + private int channel; + + this(string location) + { + this.location = location; + } + + void on() + { + writeln(location ~ " TV is on"); + } + + void off() + { + writeln(location ~ " TV is off"); + } + + void setInputChannel() + { + this.channel = 3; + writeln(location ~ " TV channel is set for DVD"); + } +} diff --git a/command/remoteundostatusmacro/tvoffcommand.d b/command/remoteundostatusmacro/tvoffcommand.d new file mode 100644 index 0000000..21e7170 --- /dev/null +++ b/command/remoteundostatusmacro/tvoffcommand.d @@ -0,0 +1,24 @@ +module command.remoteundostatusmacro.tvoffcommand; + +import command.remoteundostatusmacro.command; +import command.remoteundostatusmacro.tv; + +class TVOffCommand : Command +{ + TV tv; + + this(TV tv) + { + this.tv = tv; + } + + void execute() + { + tv.off(); + } + + void undo() + { + tv.on(); + } +} diff --git a/command/remoteundostatusmacro/tvoncommand.d b/command/remoteundostatusmacro/tvoncommand.d new file mode 100644 index 0000000..9bca6a4 --- /dev/null +++ b/command/remoteundostatusmacro/tvoncommand.d @@ -0,0 +1,25 @@ +module command.remoteundostatusmacro.tvoncommand; + +import command.remoteundostatusmacro.command; +import command.remoteundostatusmacro.tv; + +class TVOnCommand : Command +{ + TV tv; + + this(TV tv) + { + this.tv = tv; + } + + void execute() + { + tv.on(); + tv.setInputChannel(); + } + + void undo() + { + tv.off(); + } +} diff --git a/command/scheme-1.png b/command/scheme-1.png new file mode 100644 index 0000000..9f7263b Binary files /dev/null and b/command/scheme-1.png differ diff --git a/command/scheme-2.png b/command/scheme-2.png new file mode 100644 index 0000000..9149dff Binary files /dev/null and b/command/scheme-2.png differ diff --git a/command/scheme-3.png b/command/scheme-3.png new file mode 100644 index 0000000..fbe8c8a Binary files /dev/null and b/command/scheme-3.png differ diff --git a/command/simpleremotecontrol/app.d b/command/simpleremotecontrol/app.d new file mode 100644 index 0000000..d149b18 --- /dev/null +++ b/command/simpleremotecontrol/app.d @@ -0,0 +1,25 @@ +module command.simpleremotecontrol.app; + +import command.simpleremotecontrol.simpleremotecontrol; +import command.simpleremotecontrol.lightoncommand; +import command.simpleremotecontrol.lightoffcommand; +import command.simpleremotecontrol.light; +import command.simpleremotecontrol.garagedooropencommand; +import command.simpleremotecontrol.garagedoor; + +void main() +{ + auto remote = new SimpleRemoteControl(); + auto light = new Light(); + auto lightOn = new LightOnCommand(light); + auto lightOff = new LightOffCommand(light); + auto garageDoor = new GarageDoor(); + auto garageDoorOpen = new GarageDoorOpenCommand(garageDoor); + + remote.setCommand(lightOn); + remote.buttonWasPressed(); + remote.setCommand(lightOff); + remote.buttonWasPressed(); + remote.setCommand(garageDoorOpen); + remote.buttonWasPressed(); +} diff --git a/command/simpleremotecontrol/command.d b/command/simpleremotecontrol/command.d new file mode 100644 index 0000000..07102fd --- /dev/null +++ b/command/simpleremotecontrol/command.d @@ -0,0 +1,6 @@ +module command.simpleremotecontrol.command; + +interface Command +{ + void execute(); +} diff --git a/command/simpleremotecontrol/garagedoor.d b/command/simpleremotecontrol/garagedoor.d new file mode 100644 index 0000000..54732e5 --- /dev/null +++ b/command/simpleremotecontrol/garagedoor.d @@ -0,0 +1,31 @@ +module command.simpleremotecontrol.garagedoor; + +import std.stdio : writeln; + +class GarageDoor +{ + void up() + { + writeln("Garage Door is Open"); + } + + void down() + { + writeln("Garage Door is Closed"); + } + + void stop() + { + writeln("Garage Door is Stopped"); + } + + void lightOn() + { + writeln("Garage light is on"); + } + + void lightOff() + { + writeln("Garage light is off"); + } +} diff --git a/command/simpleremotecontrol/garagedooropencommand.d b/command/simpleremotecontrol/garagedooropencommand.d new file mode 100644 index 0000000..a3e00df --- /dev/null +++ b/command/simpleremotecontrol/garagedooropencommand.d @@ -0,0 +1,19 @@ +module command.simpleremotecontrol.garagedooropencommand; + +import command.simpleremotecontrol.command; +import command.simpleremotecontrol.garagedoor; + +class GarageDoorOpenCommand : Command +{ + GarageDoor garageDoor; + + this(GarageDoor garageDoor) + { + this.garageDoor = garageDoor; + } + + override void execute() + { + garageDoor.up(); + } +} diff --git a/command/simpleremotecontrol/light.d b/command/simpleremotecontrol/light.d new file mode 100644 index 0000000..b363b50 --- /dev/null +++ b/command/simpleremotecontrol/light.d @@ -0,0 +1,16 @@ +module command.simpleremotecontrol.light; + +import std.stdio : writeln; + +class Light +{ + void on() + { + writeln("Light is On"); + } + + void off() + { + writeln("Light is Off"); + } +} diff --git a/command/simpleremotecontrol/lightoffcommand.d b/command/simpleremotecontrol/lightoffcommand.d new file mode 100644 index 0000000..b12d1ea --- /dev/null +++ b/command/simpleremotecontrol/lightoffcommand.d @@ -0,0 +1,19 @@ +module command.simpleremotecontrol.lightoffcommand; + +import command.simpleremotecontrol.command; +import command.simpleremotecontrol.light; + +class LightOffCommand : Command +{ + Light light; + + this(Light light) + { + this.light = light; + } + + override void execute() + { + light.off(); + } +} diff --git a/command/simpleremotecontrol/lightoncommand.d b/command/simpleremotecontrol/lightoncommand.d new file mode 100644 index 0000000..0224a51 --- /dev/null +++ b/command/simpleremotecontrol/lightoncommand.d @@ -0,0 +1,19 @@ +module command.simpleremotecontrol.lightoncommand; + +import command.simpleremotecontrol.command; +import command.simpleremotecontrol.light; + +class LightOnCommand : Command +{ + Light light; + + this(Light light) + { + this.light = light; + } + + override void execute() + { + light.on(); + } +} diff --git a/command/simpleremotecontrol/simpleremotecontrol.d b/command/simpleremotecontrol/simpleremotecontrol.d new file mode 100644 index 0000000..2678b7a --- /dev/null +++ b/command/simpleremotecontrol/simpleremotecontrol.d @@ -0,0 +1,18 @@ +module command.simpleremotecontrol.simpleremotecontrol; + +import command.simpleremotecontrol.command; + +class SimpleRemoteControl +{ + Command slot; + + void setCommand(Command command) + { + slot = command; + } + + void buttonWasPressed() + { + slot.execute(); + } +} diff --git a/composite/README.md b/composite/README.md new file mode 100644 index 0000000..2c8d9a7 --- /dev/null +++ b/composite/README.md @@ -0,0 +1,13 @@ +# Компоновщик + +Структурный паттерн проектирования, который позволяет сгруппировать множество объектов в древовидную структуру, а затем работать с ней так, как будто это единичный объект. + +Паттерн **Компоновщик** объединяет объекты в древовидные структуры для представления иерархий «часть/целое». Компоновщик позво­ляет клиенту выполнять однородные операции с отдельными объектами и их совокупностями. + +Можно сказать, что пат­терн Компоновщик нарушает принцип одной обязанности ради ***прозрачности***. Что такое «прозрачность»? Благодаря тому, что были включены в интерфейс Component операции управле­ния как дочерними узлами, так ***и*** листьями, клиент выполняет одинаковые операции с комбинациями и листовыми узлами. Та­ким образом, вид узла становится прозрачным для клиента. Од­нако при этом приходится частично жертвовать ***безопасностью***, потому что клиент может попытаться выполнить с элементом неподходящую или бессмысленную операцию (например, по­пытаться добавить меню в листовой элемент). Речь идет о со­знательном архитектурном решении. + +## Схемы + +![scheme-1](scheme-1.png) + +![scheme-2](scheme-2.png) diff --git a/composite/composite/app.d b/composite/composite/app.d new file mode 100644 index 0000000..105f8e8 --- /dev/null +++ b/composite/composite/app.d @@ -0,0 +1,22 @@ +import companydirectory, developer, employee, manager; + +void main() +{ + auto dev1 = new Developer(100, "Lokesh Sharma", "Pro Developer"); + auto dev2 = new Developer(101, "Vinay Sharma", "Developer"); + auto engDirectory = new CompanyDirectory(); + engDirectory.addEmployee(dev1); + engDirectory.addEmployee(dev2); + + auto man1 = new Manager(200, "Kushagra Garg", "SEO Manager"); + auto man2 = new Manager(201, "Vikram Sharma ", "Kushagra's Manager"); + + auto accDirectory = new CompanyDirectory(); + accDirectory.addEmployee(man1); + accDirectory.addEmployee(man2); + + auto directory = new CompanyDirectory(); + directory.addEmployee(engDirectory); + directory.addEmployee(accDirectory); + directory.showEmployDetails(); +} diff --git a/composite/composite/companydirectory.d b/composite/composite/companydirectory.d new file mode 100644 index 0000000..7e9ee86 --- /dev/null +++ b/composite/composite/companydirectory.d @@ -0,0 +1,23 @@ +module companydirectory; + +import employee, developer, manager; +import std.stdio : writeln; +import std.algorithm : remove; + +class CompanyDirectory : Employee +{ + private Employee[] employee; + + override void showEmployDetails() + { + foreach (Employee val; employee) + { + val.showEmployDetails(); + } + } + + void addEmployee(Employee employee) + { + this.employee ~= employee; + } +} diff --git a/composite/composite/developer.d b/composite/composite/developer.d new file mode 100644 index 0000000..da292b3 --- /dev/null +++ b/composite/composite/developer.d @@ -0,0 +1,24 @@ +module developer; + +import employee; +import std.stdio : writeln; + +class Developer : Employee +{ +private: + string name; + int empId; + string position; +public: + this(int empId, string name, string position) + { + this.empId = empId; + this.name = name; + this.position = position; + } + + override void showEmployDetails() + { + writeln(empId, " ", name, " ", position); + } +} diff --git a/composite/composite/employee.d b/composite/composite/employee.d new file mode 100644 index 0000000..b46275d --- /dev/null +++ b/composite/composite/employee.d @@ -0,0 +1,6 @@ +module employee; + +interface Employee +{ + void showEmployDetails(); +} diff --git a/composite/composite/manager.d b/composite/composite/manager.d new file mode 100644 index 0000000..fce4c47 --- /dev/null +++ b/composite/composite/manager.d @@ -0,0 +1,24 @@ +module manager; + +import employee; +import std.stdio : writeln; + +class Manager : Employee +{ +private: + string name; + int empId; + string position; +public: + this(int empId, string name, string position) + { + this.empId = empId; + this.name = name; + this.position = position; + } + + override void showEmployDetails() + { + writeln(empId, " ", name, " ", position); + } +} diff --git a/composite/scheme-1.png b/composite/scheme-1.png new file mode 100644 index 0000000..af8fa02 Binary files /dev/null and b/composite/scheme-1.png differ diff --git a/composite/scheme-2.png b/composite/scheme-2.png new file mode 100644 index 0000000..fb619c5 Binary files /dev/null and b/composite/scheme-2.png differ diff --git a/decorator/README.md b/decorator/README.md new file mode 100644 index 0000000..853af3e --- /dev/null +++ b/decorator/README.md @@ -0,0 +1,15 @@ +# Декоратор + +Структурный паттерн проектирования, который позволяет динамически добавлять объектам новую функциональность, оборачивая их в полезные «обёртки». + +Типы декораторов соответствуют типам декорируемых компонентов (соответствие достигается посредством наследования или реализации интерфейса). Декораторы изменяют поведение компонентов, добавляя новую функциональность до и (или) после (или даже вместо) вызовов методов компонентов. Компонент может декорироваться любым количеством декораторов. Декораторы обычно прозрачны для клиентов компонента (если клиентский код не зависит от конкретного типа компонента). + +## Принцип + +- Согласно принципу открытости/закрытости системы должны проектироваться так, чтобы их закрытые компоненты были изолированы от новых расширений + +## Схемы + +![scheme-1](scheme-1.png) + +![scheme-2](scheme-2.png) diff --git a/decorator/coffee/app.d b/decorator/coffee/app.d new file mode 100644 index 0000000..5f54df3 --- /dev/null +++ b/decorator/coffee/app.d @@ -0,0 +1,35 @@ +module decorator.coffee.app; + +import decorator.coffee.beverage; +import decorator.coffee.espresso; +import decorator.coffee.darkroast; +import decorator.coffee.houseblend; +import decorator.coffee.decaf; +import decorator.coffee.mocha; +import decorator.coffee.milk; +import decorator.coffee.soy; +import decorator.coffee.whip; +import std.stdio : writeln; + +void print(Beverage beverage) +{ + writeln(beverage.getDescription(), " $", beverage.cost()); +} + +void main() +{ + Beverage beverage = new Espresso(); + print(beverage); + + Beverage beverage2 = new DarkRoast(); + beverage2 = new Mocha(beverage2); + beverage2 = new Mocha(beverage2); + beverage2 = new Whip(beverage2); + print(beverage2); + + Beverage beverage3 = new HouseBlend(); + beverage3 = new Soy(beverage3); + beverage3 = new Mocha(beverage3); + beverage3 = new Whip(beverage3); + print(beverage3); +} \ No newline at end of file diff --git a/decorator/coffee/beverage.d b/decorator/coffee/beverage.d new file mode 100644 index 0000000..eb9fd29 --- /dev/null +++ b/decorator/coffee/beverage.d @@ -0,0 +1,14 @@ +module decorator.coffee.beverage; + +abstract class Beverage +{ +protected: + string description = "Unknown Beverage"; +public: + string getDescription() + { + return description; + } + + double cost(); +} diff --git a/decorator/coffee/condimentdecorator.d b/decorator/coffee/condimentdecorator.d new file mode 100644 index 0000000..a379f2c --- /dev/null +++ b/decorator/coffee/condimentdecorator.d @@ -0,0 +1,8 @@ +module decorator.coffee.condimentdecorator; + +import decorator.coffee.beverage; + +abstract class CondimerDecorator : Beverage +{ + override string getDescription(); +} diff --git a/decorator/coffee/darkroast.d b/decorator/coffee/darkroast.d new file mode 100644 index 0000000..a4f4a8a --- /dev/null +++ b/decorator/coffee/darkroast.d @@ -0,0 +1,16 @@ +module decorator.coffee.darkroast; + +import decorator.coffee.beverage; + +class DarkRoast : Beverage +{ + this() + { + description = "Dark Roast Coffee"; + } + + override double cost() + { + return .99; + } +} diff --git a/decorator/coffee/decaf.d b/decorator/coffee/decaf.d new file mode 100644 index 0000000..4d73166 --- /dev/null +++ b/decorator/coffee/decaf.d @@ -0,0 +1,16 @@ +module decorator.coffee.decaf; + +import decorator.coffee.beverage; + +class Decaf : Beverage +{ + this() + { + description = "Decaf Coffee"; + } + + override double cost() + { + return 1.05; + } +} diff --git a/decorator/coffee/espresso.d b/decorator/coffee/espresso.d new file mode 100644 index 0000000..4ce1198 --- /dev/null +++ b/decorator/coffee/espresso.d @@ -0,0 +1,16 @@ +module decorator.coffee.espresso; + +import decorator.coffee.beverage; + +class Espresso : Beverage +{ + this() + { + description = "Espresso"; + } + + override double cost() + { + return 1.99; + } +} diff --git a/decorator/coffee/houseblend.d b/decorator/coffee/houseblend.d new file mode 100644 index 0000000..c637ab8 --- /dev/null +++ b/decorator/coffee/houseblend.d @@ -0,0 +1,16 @@ +module decorator.coffee.houseblend; + +import decorator.coffee.beverage; + +class HouseBlend : Beverage +{ + this() + { + description = "House Blend Coffee"; + } + + override double cost() + { + return .89; + } +} diff --git a/decorator/coffee/milk.d b/decorator/coffee/milk.d new file mode 100644 index 0000000..faa3b5a --- /dev/null +++ b/decorator/coffee/milk.d @@ -0,0 +1,25 @@ +module decorator.coffee.milk; + +import decorator.coffee.beverage; +import decorator.coffee.condimentdecorator; + +class Milk : CondimerDecorator +{ +private: + Beverage beverage; +public: + this(Beverage beverage) + { + this.beverage = beverage; + } + + override string getDescription() + { + return beverage.getDescription() ~ ", Milk"; + } + + override double cost() + { + return .10 + beverage.cost(); + } +} diff --git a/decorator/coffee/mocha.d b/decorator/coffee/mocha.d new file mode 100644 index 0000000..35f5a76 --- /dev/null +++ b/decorator/coffee/mocha.d @@ -0,0 +1,25 @@ +module decorator.coffee.mocha; + +import decorator.coffee.beverage; +import decorator.coffee.condimentdecorator; + +class Mocha : CondimerDecorator +{ +private: + Beverage beverage; +public: + this(Beverage beverage) + { + this.beverage = beverage; + } + + override string getDescription() + { + return beverage.getDescription() ~ ", Mocha"; + } + + override double cost() + { + return .20 + beverage.cost(); + } +} diff --git a/decorator/coffee/soy.d b/decorator/coffee/soy.d new file mode 100644 index 0000000..5df6ac9 --- /dev/null +++ b/decorator/coffee/soy.d @@ -0,0 +1,25 @@ +module decorator.coffee.soy; + +import decorator.coffee.beverage; +import decorator.coffee.condimentdecorator; + +class Soy : CondimerDecorator +{ +private: + Beverage beverage; +public: + this(Beverage beverage) + { + this.beverage = beverage; + } + + override string getDescription() + { + return beverage.getDescription() ~ ", Soy"; + } + + override double cost() + { + return .15 + beverage.cost(); + } +} \ No newline at end of file diff --git a/decorator/coffee/whip.d b/decorator/coffee/whip.d new file mode 100644 index 0000000..b9c8516 --- /dev/null +++ b/decorator/coffee/whip.d @@ -0,0 +1,25 @@ +module decorator.coffee.whip; + +import decorator.coffee.beverage; +import decorator.coffee.condimentdecorator; + +class Whip : CondimerDecorator +{ +private: + Beverage beverage; +public: + this(Beverage beverage) + { + this.beverage = beverage; + } + + override string getDescription() + { + return beverage.getDescription() ~ ", Whip"; + } + + override double cost() + { + return .10 + beverage.cost(); + } +} diff --git a/decorator/coffeewithsize/app.d b/decorator/coffeewithsize/app.d new file mode 100644 index 0000000..eb1a462 --- /dev/null +++ b/decorator/coffeewithsize/app.d @@ -0,0 +1,38 @@ +module decorator.coffeewithsize.app; + +import decorator.coffeewithsize.beverage; +import decorator.coffeewithsize.espresso; +import decorator.coffeewithsize.darkroast; +import decorator.coffeewithsize.houseblend; +import decorator.coffeewithsize.decaf; +import decorator.coffeewithsize.mocha; +import decorator.coffeewithsize.milk; +import decorator.coffeewithsize.soy; +import decorator.coffeewithsize.whip; +import std.stdio : writeln; + +alias Size = Beverage.Size; + +void print(Beverage beverage) +{ + writeln(beverage.getDescription(), " $", beverage.cost()); +} + +void main() +{ + Beverage beverage = new Espresso(); + print(beverage); + + Beverage beverage2 = new DarkRoast(); + beverage2 = new Mocha(beverage2); + beverage2 = new Mocha(beverage2); + beverage2 = new Whip(beverage2); + print(beverage2); + + Beverage beverage3 = new HouseBlend(); + beverage3.setSize(Size.VENTI); + beverage3 = new Soy(beverage3); + beverage3 = new Mocha(beverage3); + beverage3 = new Whip(beverage3); + print(beverage3); +} diff --git a/decorator/coffeewithsize/beverage.d b/decorator/coffeewithsize/beverage.d new file mode 100644 index 0000000..fb2a757 --- /dev/null +++ b/decorator/coffeewithsize/beverage.d @@ -0,0 +1,27 @@ +module decorator.coffeewithsize.beverage; + +abstract class Beverage +{ +protected: + string description = "Unknown Beverage"; +public: + enum Size { TALL, GRANDE, VENTI } + Size size = Size.TALL; + + string getDescription() + { + return description; + } + + void setSize(Size size) + { + this.size = size; + } + + Size getSize() + { + return size; + } + + double cost(); +} diff --git a/decorator/coffeewithsize/condimentdecorator.d b/decorator/coffeewithsize/condimentdecorator.d new file mode 100644 index 0000000..5c95cb5 --- /dev/null +++ b/decorator/coffeewithsize/condimentdecorator.d @@ -0,0 +1,8 @@ +module decorator.coffeewithsize.condimentdecorator; + +import decorator.coffeewithsize.beverage; + +abstract class CondimerDecorator : Beverage +{ + override string getDescription(); +} diff --git a/decorator/coffeewithsize/darkroast.d b/decorator/coffeewithsize/darkroast.d new file mode 100644 index 0000000..b6b1904 --- /dev/null +++ b/decorator/coffeewithsize/darkroast.d @@ -0,0 +1,16 @@ +module decorator.coffeewithsize.darkroast; + +import decorator.coffeewithsize.beverage; + +class DarkRoast : Beverage +{ + this() + { + description = "Dark Roast Coffee"; + } + + override double cost() + { + return .99; + } +} diff --git a/decorator/coffeewithsize/decaf.d b/decorator/coffeewithsize/decaf.d new file mode 100644 index 0000000..5926a07 --- /dev/null +++ b/decorator/coffeewithsize/decaf.d @@ -0,0 +1,16 @@ +module decorator.coffeewithsize.decaf; + +import decorator.coffeewithsize.beverage; + +class Decaf : Beverage +{ + this() + { + description = "Decaf Coffee"; + } + + override double cost() + { + return 1.05; + } +} diff --git a/decorator/coffeewithsize/espresso.d b/decorator/coffeewithsize/espresso.d new file mode 100644 index 0000000..f46615b --- /dev/null +++ b/decorator/coffeewithsize/espresso.d @@ -0,0 +1,16 @@ +module decorator.coffeewithsize.espresso; + +import decorator.coffeewithsize.beverage; + +class Espresso : Beverage +{ + this() + { + description = "Espresso"; + } + + override double cost() + { + return 1.99; + } +} diff --git a/decorator/coffeewithsize/houseblend.d b/decorator/coffeewithsize/houseblend.d new file mode 100644 index 0000000..9304a34 --- /dev/null +++ b/decorator/coffeewithsize/houseblend.d @@ -0,0 +1,16 @@ +module decorator.coffeewithsize.houseblend; + +import decorator.coffeewithsize.beverage; + +class HouseBlend : Beverage +{ + this() + { + description = "House Blend Coffee"; + } + + override double cost() + { + return .89; + } +} diff --git a/decorator/coffeewithsize/milk.d b/decorator/coffeewithsize/milk.d new file mode 100644 index 0000000..03eb61a --- /dev/null +++ b/decorator/coffeewithsize/milk.d @@ -0,0 +1,25 @@ +module decorator.coffeewithsize.milk; + +import decorator.coffeewithsize.beverage; +import decorator.coffeewithsize.condimentdecorator; + +class Milk : CondimerDecorator +{ +private: + Beverage beverage; +public: + this(Beverage beverage) + { + this.beverage = beverage; + } + + override string getDescription() + { + return beverage.getDescription() ~ ", Milk"; + } + + override double cost() + { + return .10 + beverage.cost(); + } +} diff --git a/decorator/coffeewithsize/mocha.d b/decorator/coffeewithsize/mocha.d new file mode 100644 index 0000000..db2c703 --- /dev/null +++ b/decorator/coffeewithsize/mocha.d @@ -0,0 +1,25 @@ +module decorator.coffeewithsize.mocha; + +import decorator.coffeewithsize.beverage; +import decorator.coffeewithsize.condimentdecorator; + +class Mocha : CondimerDecorator +{ +private: + Beverage beverage; +public: + this(Beverage beverage) + { + this.beverage = beverage; + } + + override string getDescription() + { + return beverage.getDescription() ~ ", Mocha"; + } + + override double cost() + { + return .20 + beverage.cost(); + } +} diff --git a/decorator/coffeewithsize/soy.d b/decorator/coffeewithsize/soy.d new file mode 100644 index 0000000..b6c94c2 --- /dev/null +++ b/decorator/coffeewithsize/soy.d @@ -0,0 +1,38 @@ +module decorator.coffeewithsize.soy; + +import decorator.coffeewithsize.beverage; +import decorator.coffeewithsize.condimentdecorator; + +class Soy : CondimerDecorator +{ +private: + Beverage beverage; +public: + this(Beverage beverage) + { + this.beverage = beverage; + } + + override string getDescription() + { + return beverage.getDescription() ~ ", Soy"; + } + + override double cost() + { + double cost = beverage.cost(); + if (beverage.getSize() == Size.TALL) + { + cost += .10; + } + else if (beverage.getSize() == Size.GRANDE) + { + cost += .15; + } + else if (beverage.getSize() == Size.VENTI) + { + cost += .20; + } + return cost; + } +} \ No newline at end of file diff --git a/decorator/coffeewithsize/whip.d b/decorator/coffeewithsize/whip.d new file mode 100644 index 0000000..72a9791 --- /dev/null +++ b/decorator/coffeewithsize/whip.d @@ -0,0 +1,25 @@ +module decorator.coffeewithsize.whip; + +import decorator.coffeewithsize.beverage; +import decorator.coffeewithsize.condimentdecorator; + +class Whip : CondimerDecorator +{ +private: + Beverage beverage; +public: + this(Beverage beverage) + { + this.beverage = beverage; + } + + override string getDescription() + { + return beverage.getDescription() ~ ", Whip"; + } + + override double cost() + { + return .10 + beverage.cost(); + } +} diff --git a/decorator/scheme-1.png b/decorator/scheme-1.png new file mode 100644 index 0000000..2a8fa33 Binary files /dev/null and b/decorator/scheme-1.png differ diff --git a/decorator/scheme-2.png b/decorator/scheme-2.png new file mode 100644 index 0000000..ab35e3c Binary files /dev/null and b/decorator/scheme-2.png differ diff --git a/facade/README.md b/facade/README.md new file mode 100644 index 0000000..1d5e918 --- /dev/null +++ b/facade/README.md @@ -0,0 +1,17 @@ +# Фасад + +Структурный паттерн проектирования, который предоставляет простой интерфейс к сложной системе классов, библиотеке или фреймворку. + +Паттерн **Фасад** предоставляет унифицированный интерфейс к группе интерфейсов подсистемы. Фасад определяет высокоуровневый интерфейс, упрощающий работу с подсистемой. + +# Принципы + +- Принцип минимальной информированности: общайтесь только с близкими друзьями. + +## Схемы + +![scheme-1](scheme-1.png) + +![scheme-2](scheme-2.png) + +![scheme-3](scheme-3.png) diff --git a/facade/hometheater/amplifier.d b/facade/hometheater/amplifier.d new file mode 100644 index 0000000..12d91c6 --- /dev/null +++ b/facade/hometheater/amplifier.d @@ -0,0 +1,59 @@ +module amplifier; + +import tuner, streamingplayer; +import std.stdio : writeln; +import std.conv : to; + +class Amplifier +{ + private string description; + private Tuner tuner; + private StreamingPlayer player; + + this(string description) + { + this.description = description; + } + + void on() + { + writeln(description ~ " on"); + } + + void off() + { + writeln(description ~ " off"); + } + + void setStereoSound() + { + writeln(description ~ " stereo mode on"); + } + + void setSurroundSound() + { + writeln(description ~ " surround sound on (5 speakers, 1 subwoofer)"); + } + + void setVolume(int level) + { + writeln(description ~ " setting volume to " ~ level.to!string); + } + + void setTuner(Tuner tuner) + { + writeln(description ~ " setting tuner to " ~ tuner.to!string); + this.tuner = tuner; + } + + void setStreamingPlayer(StreamingPlayer player) + { + writeln(description ~ " setting Streaming player to " ~ player.to!string); + this.player = player; + } + + override string toString() const + { + return description; + } +} diff --git a/facade/hometheater/app.d b/facade/hometheater/app.d new file mode 100644 index 0000000..46a25c2 --- /dev/null +++ b/facade/hometheater/app.d @@ -0,0 +1,21 @@ +import amplifier, tuner, streamingplayer, cdplayer, projector, theaterlights, screen, popcornpopper, hometheaterfacade; + +void main() +{ + auto amp = new Amplifier("Amplifier"); + auto tuner = new Tuner("AM/FM Tuner", amp); + auto player = new StreamingPlayer("Streaming Player", amp); + auto cd = new CdPlayer("CD Player", amp); + auto projector = new Projector("Projector", player); + auto lights = new TheaterLights("Theater Ceiling Lights"); + auto screen = new Screen("Theater Screen"); + auto popper = new PopcornPopper("Popcorn Popper"); + + auto homeTheater = new HomeTheaterFacade(amp, tuner, player, cd, projector, lights, screen, popper); + + homeTheater.watchMovie("Raiders of the Lost Ark"); + homeTheater.endMovie(); + + homeTheater.listenToRadio(101.5); + homeTheater.endRadio(); +} diff --git a/facade/hometheater/cdplayer.d b/facade/hometheater/cdplayer.d new file mode 100644 index 0000000..171a2fb --- /dev/null +++ b/facade/hometheater/cdplayer.d @@ -0,0 +1,71 @@ +module cdplayer; + +import amplifier; +import std.stdio : writeln; +import std.conv : to; + +class CdPlayer +{ + private string description; + private int currentTrack; + private Amplifier amplifier; + private string title; + + this(string description, Amplifier amplifier) + { + this.description = description; + this.amplifier = amplifier; + } + + void on() + { + writeln(description ~ " on"); + } + + void off() + { + writeln(description ~ " off"); + } + + void eject() + { + title = null; + writeln(description ~ " eject"); + } + + void play(string title) + { + this.title = title; + currentTrack = 0; + writeln(description ~ " playing \"" ~ title ~ "\""); + } + + void play(int track) + { + if (title is null) + { + writeln(description ~ " can't play track " ~ currentTrack.to!string ~ " no cd inserted"); + } + else + { + currentTrack = track; + writeln(description ~ " playing track " ~ currentTrack.to!string); + } + } + + void stop() + { + currentTrack = 0; + writeln(description ~ " stopped"); + } + + void pause() + { + writeln(description ~ " paused \"" ~ title ~ "\""); + } + + override string toString() const + { + return description; + } +} diff --git a/facade/hometheater/hometheaterfacade.d b/facade/hometheater/hometheaterfacade.d new file mode 100644 index 0000000..2307180 --- /dev/null +++ b/facade/hometheater/hometheaterfacade.d @@ -0,0 +1,82 @@ +module hometheaterfacade; + +import std.stdio : writeln; +import amplifier, tuner, streamingplayer, cdplayer, projector, theaterlights, screen, popcornpopper; + +class HomeTheaterFacade +{ + private Amplifier amp; + private Tuner tuner; + private StreamingPlayer player; + private CdPlayer cd; + private Projector projector; + private TheaterLights lights; + private Screen screen; + private PopcornPopper popper; + + this(Amplifier amp, + Tuner tuner, + StreamingPlayer player, + CdPlayer cd, + Projector projector, + TheaterLights lights, + Screen screen, + PopcornPopper popper) + { + this.amp = amp; + this.tuner = tuner; + this.player = player; + this.cd = cd; + this.projector = projector; + this.lights = lights; + this.screen = screen; + this.popper = popper; + } + + void watchMovie(string movie) + { + writeln("Get ready to watch a movie..."); + popper.on(); + popper.pop(); + lights.dim(10); + screen.down(); + projector.on(); + projector.wideScreenMode(); + amp.on(); + amp.setStreamingPlayer(player); + amp.setSurroundSound(); + amp.setVolume(5); + player.on(); + player.play(movie); + } + + + void endMovie() + { + writeln("Shutting movie theater down..."); + popper.off(); + lights.on(); + screen.up(); + projector.off(); + amp.off(); + player.stop(); + player.off(); + } + + void listenToRadio(double frequency) + { + writeln("Tuning in the airwaves..."); + tuner.on(); + tuner.setFrequency(frequency); + amp.on(); + amp.setVolume(5); + amp.setTuner(tuner); + } + + void endRadio() + { + writeln("Shutting down the tuner..."); + tuner.off(); + amp.off(); + } +} diff --git a/facade/hometheater/popcornpopper.d b/facade/hometheater/popcornpopper.d new file mode 100644 index 0000000..f417142 --- /dev/null +++ b/facade/hometheater/popcornpopper.d @@ -0,0 +1,34 @@ +module popcornpopper; + +import std.stdio : writeln; + + +class PopcornPopper +{ + private string description; + + this(string description) + { + this.description = description; + } + + void on() + { + writeln(description ~ " on"); + } + + void off() + { + writeln(description ~ " off"); + } + + void pop() + { + writeln(description ~ " popping popcorn!"); + } + + override string toString() const + { + return description; + } +} diff --git a/facade/hometheater/projector.d b/facade/hometheater/projector.d new file mode 100644 index 0000000..a8885fb --- /dev/null +++ b/facade/hometheater/projector.d @@ -0,0 +1,41 @@ +module projector; + +import streamingplayer; +import std.stdio : writeln; + +class Projector +{ + private string description; + private StreamingPlayer player; + + this(string description, StreamingPlayer player) + { + this.description = description; + this.player = player; + } + + void on() + { + writeln(description ~ " on"); + } + + void off() + { + writeln(description ~ " off"); + } + + void wideScreenMode() + { + writeln(description ~ " in widescreen mode (16x9 aspect ratio)"); + } + + void tvMode() + { + writeln(description ~ " in tv mode (4x3 aspect ratio)"); + } + + override string toString() const + { + return description; + } +} diff --git a/facade/hometheater/screen.d b/facade/hometheater/screen.d new file mode 100644 index 0000000..1cc5ae3 --- /dev/null +++ b/facade/hometheater/screen.d @@ -0,0 +1,28 @@ +module screen; + +import std.stdio : writeln; + +class Screen +{ + private string description; + + this(string description) + { + this.description = description; + } + + void up() + { + writeln(description ~ " going up"); + } + + void down() + { + writeln(description ~ " going down"); + } + + override string toString() const + { + return description; + } +} diff --git a/facade/hometheater/streamingplayer.d b/facade/hometheater/streamingplayer.d new file mode 100644 index 0000000..2438332 --- /dev/null +++ b/facade/hometheater/streamingplayer.d @@ -0,0 +1,75 @@ +module streamingplayer; + +import amplifier; +import std.stdio : writeln; +import std.conv : to; + +class StreamingPlayer +{ + private string description; + private int currentChapter; + private Amplifier amplifier; + private string movie; + + this(string description, Amplifier amplifier) + { + this.description = description; + this.amplifier = amplifier; + } + + void on() + { + writeln(description ~ " on"); + } + + void off() + { + writeln(description ~ " off"); + } + + void play(string movie) + { + this.movie = movie; + currentChapter = 0; + writeln(description ~ " playing \"" ~ movie ~ "\""); + } + + void play(int chapter) + { + if (movie is null) + { + writeln(description ~ " can't play chapter " ~ chapter.to!string ~ " on movie selected"); + } + else + { + currentChapter = chapter; + writeln(description ~ " playing chapter " ~ currentChapter.to!string ~ " off \"" ~ movie ~ "\""); + } + } + + void stop() + { + currentChapter = 0; + writeln(description ~ " stopped \"" ~ movie ~ "\""); + } + + void pause() + { + writeln(description ~ " paused \"" ~ movie ~ "\""); + } + + void setTwoChannelAudio() + { + writeln(description ~ " set two channel audio"); + } + + void setSurroundAudio() + { + writeln(description ~ " set surround audio"); + } + + override string toString() const + { + return description; + } +} diff --git a/facade/hometheater/theaterlights.d b/facade/hometheater/theaterlights.d new file mode 100644 index 0000000..42da269 --- /dev/null +++ b/facade/hometheater/theaterlights.d @@ -0,0 +1,34 @@ +module theaterlights; + +import std.stdio : writeln; +import std.conv : to; + +class TheaterLights +{ + private string description; + + this(string description) + { + this.description = description; + } + + void on() + { + writeln(description ~ " on"); + } + + void off() + { + writeln(description ~ " off"); + } + + void dim(int level) + { + writeln(description ~ " dimming to " ~ level.to!string ~ "%"); + } + + override string toString() const + { + return description; + } +} diff --git a/facade/hometheater/tuner.d b/facade/hometheater/tuner.d new file mode 100644 index 0000000..732864a --- /dev/null +++ b/facade/hometheater/tuner.d @@ -0,0 +1,49 @@ +module tuner; + +import amplifier; +import std.stdio : writeln; +import std.conv : to; + +class Tuner +{ + private string description; + private Amplifier amplifier; + private double frequency; + + this(string description, Amplifier amplifier) + { + this.description = description; + this.amplifier = amplifier; + } + + void on() + { + writeln(description ~ " on"); + } + + void off() + { + writeln(description ~ " off"); + } + + void setFrequency(double frequency) + { + writeln(description ~ " setting frequency to " ~ frequency.to!string); + this.frequency = frequency; + } + + void setAm() + { + writeln(description ~ " setting AM mode"); + } + + void setFm() + { + writeln(description ~ " setting FM mode"); + } + + override string toString() const + { + return description; + } +} diff --git a/facade/scheme-1.png b/facade/scheme-1.png new file mode 100644 index 0000000..b02d83b Binary files /dev/null and b/facade/scheme-1.png differ diff --git a/facade/scheme-2.png b/facade/scheme-2.png new file mode 100644 index 0000000..2d1958a Binary files /dev/null and b/facade/scheme-2.png differ diff --git a/facade/scheme-3.png b/facade/scheme-3.png new file mode 100644 index 0000000..73192b6 Binary files /dev/null and b/facade/scheme-3.png differ diff --git a/factorymethod/README.md b/factorymethod/README.md new file mode 100644 index 0000000..92f6dd2 --- /dev/null +++ b/factorymethod/README.md @@ -0,0 +1,23 @@ +# Фабричный метод + +Порождающий паттерн проектирования, который определяет общий интерфейс для создания объектов в суперклассе, позволяя подклассам изменять тип создаваемых объектов. + +Паттерн **Фабричный Метод** определяет интерфейс создания объекта, но позволяет субклассам выбрать создаваемый экземпляр. Таким образом, Фабричный Метод делегирует операцию создания экземпляра субклассам. + +## Принципы + +- Код должен зависеть от абстракций, а не от конкретных классов + +## Схемы + +![scheme-1](scheme-1.png) + +![scheme-2](scheme-2.png) + +![scheme-3](scheme-3.png) + +![scheme-4](scheme-4.png) + +![scheme-5](scheme-5.png) + +![scheme-6](scheme-6.png) diff --git a/factorymethod/pizzafactorymethod/app.d b/factorymethod/pizzafactorymethod/app.d new file mode 100644 index 0000000..2516e75 --- /dev/null +++ b/factorymethod/pizzafactorymethod/app.d @@ -0,0 +1,37 @@ +module factorymethod.pizzafactorymethod.app; + +import factorymethod.pizzafactorymethod.pizza; +import factorymethod.pizzafactorymethod.pizzastore; +import factorymethod.pizzafactorymethod.nypizzastore; +import factorymethod.pizzafactorymethod.chicagopizzastore; +import std.stdio : writeln; + +void main() +{ + PizzaStore nyStore = new NYPizzaStore(); + PizzaStore chicagoStore = new ChicagoPizzaStore(); + + Pizza pizza = nyStore.orderPizza("cheese"); + writeln("Ethan ordered a ", pizza.getName()); + + pizza = chicagoStore.orderPizza("cheese"); + writeln("Joel ordered a ", pizza.getName()); + + pizza = nyStore.orderPizza("clam"); + writeln("Ethan ordered a ", pizza.getName()); + + pizza = chicagoStore.orderPizza("clam"); + writeln("Joel ordered a ", pizza.getName()); + + pizza = nyStore.orderPizza("pepperoni"); + writeln("Ethan ordered a ", pizza.getName()); + + pizza = chicagoStore.orderPizza("pepperoni"); + writeln("Joel ordered a ", pizza.getName()); + + pizza = nyStore.orderPizza("veggie"); + writeln("Ethan ordered a ", pizza.getName()); + + pizza = chicagoStore.orderPizza("veggie"); + writeln("Joel ordered a ", pizza.getName()); +} diff --git a/factorymethod/pizzafactorymethod/chicagopizzastore.d b/factorymethod/pizzafactorymethod/chicagopizzastore.d new file mode 100644 index 0000000..a3de9d7 --- /dev/null +++ b/factorymethod/pizzafactorymethod/chicagopizzastore.d @@ -0,0 +1,35 @@ +module factorymethod.pizzafactorymethod.chicagopizzastore; + +import factorymethod.pizzafactorymethod.pizza; +import factorymethod.pizzafactorymethod.pizzastore; +import factorymethod.pizzafactorymethod.chicagostylecheesepizza; +import factorymethod.pizzafactorymethod.chicagostyleclampizza; +import factorymethod.pizzafactorymethod.chicagostylepepperonipizza; +import factorymethod.pizzafactorymethod.chicagostyleveggiepizza; + +class ChicagoPizzaStore : PizzaStore +{ + override Pizza createPizza(string item) + { + if (item == "cheese") + { + return new ChicagoStyleCheesePizza(); + } + else if (item == "veggie") + { + return new ChicagoStyleVeggiePizza(); + } + else if (item == "clam") + { + return new ChicagoStyleClamPizza(); + } + else if (item == "pepperoni") + { + return new ChicagoStylePepperoniPizza(); + } + else + { + return null; + } + } +} diff --git a/factorymethod/pizzafactorymethod/chicagostylecheesepizza.d b/factorymethod/pizzafactorymethod/chicagostylecheesepizza.d new file mode 100644 index 0000000..45d5d69 --- /dev/null +++ b/factorymethod/pizzafactorymethod/chicagostylecheesepizza.d @@ -0,0 +1,21 @@ +module factorymethod.pizzafactorymethod.chicagostylecheesepizza; + +import factorymethod.pizzafactorymethod.pizza; +import std.stdio : writeln; + +class ChicagoStyleCheesePizza : Pizza +{ + this() + { + name = "Chicago Style Deep Dish Cheese Pizza"; + dough = "Extra Thick Crust Dough"; + sauce = "Plum Tomato Sauce"; + + toppings ~= "Shredded Mozzarella Cheese"; + } + + override void cut() + { + writeln("Cutting the pizza into square slices"); + } +} diff --git a/factorymethod/pizzafactorymethod/chicagostyleclampizza.d b/factorymethod/pizzafactorymethod/chicagostyleclampizza.d new file mode 100644 index 0000000..fe1623f --- /dev/null +++ b/factorymethod/pizzafactorymethod/chicagostyleclampizza.d @@ -0,0 +1,22 @@ +module factorymethod.pizzafactorymethod.chicagostyleclampizza; + +import factorymethod.pizzafactorymethod.pizza; +import std.stdio : writeln; + +class ChicagoStyleClamPizza : Pizza +{ + this() + { + name = "Chicago Style Clam Pizza"; + dough = "Extra Thick Crust Dough"; + sauce = "Plum Tomato Sauce"; + + toppings ~= "Shredded Mozzarella Cheese"; + toppings ~= "Frozen Clams from Chesapeake Bay"; + } + + override void cut() + { + writeln("Cutting the pizza into square slices"); + } +} diff --git a/factorymethod/pizzafactorymethod/chicagostylepepperonipizza.d b/factorymethod/pizzafactorymethod/chicagostylepepperonipizza.d new file mode 100644 index 0000000..5f8c1a1 --- /dev/null +++ b/factorymethod/pizzafactorymethod/chicagostylepepperonipizza.d @@ -0,0 +1,25 @@ +module factorymethod.pizzafactorymethod.chicagostylepepperonipizza; + +import factorymethod.pizzafactorymethod.pizza; +import std.stdio : writeln; + +class ChicagoStylePepperoniPizza : Pizza +{ + this() + { + name = "Chicago Style Pepperoni Pizza"; + dough = "Extra Thick Crust Dough"; + sauce = "Plum Tomato Sauce"; + + toppings ~= "Shredded Mozzarella Cheese"; + toppings ~= "Black Olives"; + toppings ~= "Spinach"; + toppings ~= "Eggplant"; + toppings ~= "Sliced Pepperoni"; + } + + override void cut() + { + writeln("Cutting the pizza into square slices"); + } +} diff --git a/factorymethod/pizzafactorymethod/chicagostyleveggiepizza.d b/factorymethod/pizzafactorymethod/chicagostyleveggiepizza.d new file mode 100644 index 0000000..625ed98 --- /dev/null +++ b/factorymethod/pizzafactorymethod/chicagostyleveggiepizza.d @@ -0,0 +1,24 @@ +module factorymethod.pizzafactorymethod.chicagostyleveggiepizza; + +import factorymethod.pizzafactorymethod.pizza; +import std.stdio : writeln; + +class ChicagoStyleVeggiePizza : Pizza +{ + this() + { + name = "Chicago Deep Dish Veggie Pizza"; + dough = "Extra Thick Crust Dough"; + sauce = "Plum Tomato Sauce"; + + toppings ~= "Shredded Mozzarella Cheese"; + toppings ~= "Black Olives"; + toppings ~= "Spinach"; + toppings ~= "Eggplant"; + } + + override void cut() + { + writeln("Cutting the pizza into square slices"); + } +} diff --git a/factorymethod/pizzafactorymethod/nypizzastore.d b/factorymethod/pizzafactorymethod/nypizzastore.d new file mode 100644 index 0000000..570ae81 --- /dev/null +++ b/factorymethod/pizzafactorymethod/nypizzastore.d @@ -0,0 +1,35 @@ +module factorymethod.pizzafactorymethod.nypizzastore; + +import factorymethod.pizzafactorymethod.pizza; +import factorymethod.pizzafactorymethod.pizzastore; +import factorymethod.pizzafactorymethod.nystylecheesepizza; +import factorymethod.pizzafactorymethod.nystyleclampizza; +import factorymethod.pizzafactorymethod.nystylepepperonipizza; +import factorymethod.pizzafactorymethod.nystyleveggiepizza; + +class NYPizzaStore : PizzaStore +{ + override Pizza createPizza(string item) + { + if (item == "cheese") + { + return new NYStyleCheesePizza(); + } + else if (item == "veggie") + { + return new NYStyleVeggiePizza(); + } + else if (item == "clam") + { + return new NYStyleClamPizza(); + } + else if (item == "pepperoni") + { + return new NYStylePepperoniPizza(); + } + else + { + return null; + } + } +} diff --git a/factorymethod/pizzafactorymethod/nystylecheesepizza.d b/factorymethod/pizzafactorymethod/nystylecheesepizza.d new file mode 100644 index 0000000..c4a3247 --- /dev/null +++ b/factorymethod/pizzafactorymethod/nystylecheesepizza.d @@ -0,0 +1,15 @@ +module factorymethod.pizzafactorymethod.nystylecheesepizza; + +import factorymethod.pizzafactorymethod.pizza; + +class NYStyleCheesePizza : Pizza +{ + this() + { + name = "NY Style Sauce and Cheese Pizza"; + dough = "Thin Crust Dough"; + sauce = "Marinara Sauce"; + + toppings ~= "Grated Reggiano Cheese"; + } +} diff --git a/factorymethod/pizzafactorymethod/nystyleclampizza.d b/factorymethod/pizzafactorymethod/nystyleclampizza.d new file mode 100644 index 0000000..4e69d07 --- /dev/null +++ b/factorymethod/pizzafactorymethod/nystyleclampizza.d @@ -0,0 +1,16 @@ +module factorymethod.pizzafactorymethod.nystyleclampizza; + +import factorymethod.pizzafactorymethod.pizza; + +class NYStyleClamPizza : Pizza +{ + this() + { + name = "NY Style Clam Pizza"; + dough = "Thin Crust Dough"; + sauce = "Marinara Sauce"; + + toppings ~= "Grated Reggiano Cheese"; + toppings ~= "Fresh Clams from Long Island Sound"; + } +} diff --git a/factorymethod/pizzafactorymethod/nystylepepperonipizza.d b/factorymethod/pizzafactorymethod/nystylepepperonipizza.d new file mode 100644 index 0000000..98c0e4d --- /dev/null +++ b/factorymethod/pizzafactorymethod/nystylepepperonipizza.d @@ -0,0 +1,20 @@ +module factorymethod.pizzafactorymethod.nystylepepperonipizza; + +import factorymethod.pizzafactorymethod.pizza; + +class NYStylePepperoniPizza : Pizza +{ + this() + { + name = "NY Style Pepperoni Pizza"; + dough = "Thin Crust Dough"; + sauce = "Marinara Sauce"; + + toppings ~= "Grated Reggiano Cheese"; + toppings ~= "Sliced Pepperoni"; + toppings ~= "Garlic"; + toppings ~= "Onion"; + toppings ~= "Mushrooms"; + toppings ~= "Red Pepper"; + } +} diff --git a/factorymethod/pizzafactorymethod/nystyleveggiepizza.d b/factorymethod/pizzafactorymethod/nystyleveggiepizza.d new file mode 100644 index 0000000..8a38a59 --- /dev/null +++ b/factorymethod/pizzafactorymethod/nystyleveggiepizza.d @@ -0,0 +1,19 @@ +module factorymethod.pizzafactorymethod.nystyleveggiepizza; + +import factorymethod.pizzafactorymethod.pizza; + +class NYStyleVeggiePizza : Pizza +{ + this() + { + name = "NY Style Veggie Pizza"; + dough = "Thin Crust Dough"; + sauce = "Marinara Sauce"; + + toppings ~= "Grated Reggiano Cheese"; + toppings ~= "Garlic"; + toppings ~= "Onion"; + toppings ~= "Mushrooms"; + toppings ~= "Red Pepper"; + } +} diff --git a/factorymethod/pizzafactorymethod/pizza.d b/factorymethod/pizzafactorymethod/pizza.d new file mode 100644 index 0000000..86c15b7 --- /dev/null +++ b/factorymethod/pizzafactorymethod/pizza.d @@ -0,0 +1,57 @@ +module factorymethod.pizzafactorymethod.pizza; + +import std.stdio : writeln; + +abstract class Pizza +{ +protected: + string name; + string dough; + string sauce; + string[] toppings; +public: + string getName() + { + return name; + } + + void prepare() + { + writeln("Prepare " ~ name); + writeln("Tossing dough..."); + writeln("Adding sauce..."); + writeln("Adding toppings: "); + foreach (val; toppings) + { + writeln(" " ~ val); + } + } + + void bake() + { + writeln("Bake for 25 minutes at 350"); + } + + void cut() + { + writeln("Cut the pizza into diagonal slices"); + } + + void box() + { + writeln("Place pizza in official PizzaStore box"); + } + + override string toString() const @safe pure nothrow + { + string s; + s ~= "---- " ~ name ~ " ----\n"; + s ~= dough ~ "\n"; + s ~= sauce ~ "\n"; + foreach (val; toppings) + { + s ~= val ~ '\n'; + } + return s; + } +} diff --git a/factorymethod/pizzafactorymethod/pizzastore.d b/factorymethod/pizzafactorymethod/pizzastore.d new file mode 100644 index 0000000..4b91319 --- /dev/null +++ b/factorymethod/pizzafactorymethod/pizzastore.d @@ -0,0 +1,23 @@ +module factorymethod.pizzafactorymethod.pizzastore; + +import factorymethod.pizzafactorymethod.pizza; +import std.stdio : writeln; + +class PizzaStore +{ + abstract Pizza createPizza(string type); + + Pizza orderPizza(string type) + { + Pizza pizza = createPizza(type); + + writeln("--- Making a " ~ pizza.getName() ~ " ---"); + + pizza.prepare(); + pizza.bake(); + pizza.cut(); + pizza.box(); + + return pizza; + } +} diff --git a/factorymethod/pizzasimple/app.d b/factorymethod/pizzasimple/app.d new file mode 100644 index 0000000..8d920c9 --- /dev/null +++ b/factorymethod/pizzasimple/app.d @@ -0,0 +1,24 @@ +module factorymethod.pizzasimple.app; + +import factorymethod.pizzasimple.simplepizzafactory; +import factorymethod.pizzasimple.pizzastore; +import factorymethod.pizzasimple.pizza; +import std.stdio : writeln; + +void main() +{ + SimplePizzaFactory factory = new SimplePizzaFactory(); + PizzaStore store = new PizzaStore(factory); + + Pizza pizza = store.orderPizza("cheese"); + writeln("Мы заказали ", pizza.getName()); + writeln(pizza); + + pizza = store.orderPizza("veggie"); + writeln("Мы заказали ", pizza.getName()); + writeln(pizza.toString()); + + pizza = store.orderPizza("pepperoni"); + writeln("Мы заказали ", pizza.getName()); + writeln(pizza.toString()); +} diff --git a/factorymethod/pizzasimple/cheesepizza.d b/factorymethod/pizzasimple/cheesepizza.d new file mode 100644 index 0000000..da2ae74 --- /dev/null +++ b/factorymethod/pizzasimple/cheesepizza.d @@ -0,0 +1,15 @@ +module factorymethod.pizzasimple.cheesepizza; + +import factorymethod.pizzasimple.pizza; + +class CheesePizza : Pizza +{ + this() + { + name = "Сырная пицца"; + dough = "Обычная корочка"; + sauce = "Соус для пиццы Маринара"; + toppings ~= "Свежая моцарелла"; + toppings ~= "Пармезан"; + } +} diff --git a/factorymethod/pizzasimple/clampizza.d b/factorymethod/pizzasimple/clampizza.d new file mode 100644 index 0000000..e540a05 --- /dev/null +++ b/factorymethod/pizzasimple/clampizza.d @@ -0,0 +1,15 @@ +module factorymethod.pizzasimple.clampizza; + +import factorymethod.pizzasimple.pizza; + +class ClamPizza : Pizza +{ + this() + { + name = "Пицца с моллюсками"; + dough = "Тонкая корочка"; + sauce = "Белый чесночный соус"; + toppings ~= "Моллюски"; + toppings ~= "Тертый сыр пармезан"; + } +} diff --git a/factorymethod/pizzasimple/pepperonipizza.d b/factorymethod/pizzasimple/pepperonipizza.d new file mode 100644 index 0000000..0bdfa1d --- /dev/null +++ b/factorymethod/pizzasimple/pepperonipizza.d @@ -0,0 +1,16 @@ +module factorymethod.pizzasimple.pepperonipizza; + +import factorymethod.pizzasimple.pizza; + +class PepperoniPizza : Pizza +{ + this() + { + name = "Пицца с пепперони"; + dough = "Корка"; + sauce = "Соус Маринара"; + toppings ~= "Нарезанные пепперони"; + toppings ~= "Нарезанный лук"; + toppings ~= "Тертый сыр пармезан"; + } +} diff --git a/factorymethod/pizzasimple/pizza.d b/factorymethod/pizzasimple/pizza.d new file mode 100644 index 0000000..07980f7 --- /dev/null +++ b/factorymethod/pizzasimple/pizza.d @@ -0,0 +1,50 @@ +module factorymethod.pizzasimple.pizza; + +import std.stdio : writeln; + +abstract class Pizza +{ +protected: + string name; + string dough; + string sauce; + string[] toppings; +public: + string getName() + { + return name; + } + + void prepare() + { + writeln("Подготовка " ~ name); + } + + void bake() + { + writeln("Выпечка " ~ name); + } + + void cut() + { + writeln("Резка " ~ name); + } + + void box() + { + writeln("Упаковка " ~ name); + } + + override string toString() const @safe pure nothrow + { + string s; + s ~= "---- " ~ name ~ " ----\n"; + s ~= dough ~ "\n"; + s ~= sauce ~ "\n"; + foreach (val; toppings) + { + s ~= val ~ '\n'; + } + return s; + } +} diff --git a/factorymethod/pizzasimple/pizzastore.d b/factorymethod/pizzasimple/pizzastore.d new file mode 100644 index 0000000..953bb72 --- /dev/null +++ b/factorymethod/pizzasimple/pizzastore.d @@ -0,0 +1,28 @@ +module factorymethod.pizzasimple.pizzastore; + +import factorymethod.pizzasimple.simplepizzafactory; +import factorymethod.pizzasimple.pizza; + +class PizzaStore +{ + SimplePizzaFactory factory; + + this(SimplePizzaFactory factory) + { + this.factory = factory; + } + + Pizza orderPizza(string type) + { + Pizza pizza; + + pizza = factory.createPizza(type); + + pizza.prepare(); + pizza.bake(); + pizza.cut(); + pizza.box(); + + return pizza; + } +} diff --git a/factorymethod/pizzasimple/simplepizzafactory.d b/factorymethod/pizzasimple/simplepizzafactory.d new file mode 100644 index 0000000..72ca057 --- /dev/null +++ b/factorymethod/pizzasimple/simplepizzafactory.d @@ -0,0 +1,33 @@ +module factorymethod.pizzasimple.simplepizzafactory; + +import factorymethod.pizzasimple.pizza; +import factorymethod.pizzasimple.cheesepizza; +import factorymethod.pizzasimple.pepperonipizza; +import factorymethod.pizzasimple.clampizza; +import factorymethod.pizzasimple.veggiepizza; + +class SimplePizzaFactory +{ + Pizza createPizza(string type) + { + Pizza pizza = null; + + if (type == "cheese") + { + pizza = new CheesePizza(); + } + else if (type == "pepperoni") + { + pizza = new PepperoniPizza(); + } + else if (type == "clam") + { + pizza = new ClamPizza(); + } + else if (type == "veggie") + { + pizza = new VeggiePizza(); + } + return pizza; + } +} diff --git a/factorymethod/pizzasimple/veggiepizza.d b/factorymethod/pizzasimple/veggiepizza.d new file mode 100644 index 0000000..e3c3428 --- /dev/null +++ b/factorymethod/pizzasimple/veggiepizza.d @@ -0,0 +1,19 @@ +module factorymethod.pizzasimple.veggiepizza; + +import factorymethod.pizzasimple.pizza; + +class VeggiePizza : Pizza +{ + this() + { + name = "Вегетарианская пицца"; + dough = "Корка"; + sauce = "Соус Маринара"; + toppings ~= "Тертая моцарелла"; + toppings ~= "Тертый пармезан"; + toppings ~= "Нарезанный кубиками лук"; + toppings ~= "Нарезанные грибы"; + toppings ~= "Нарезанный красный перец"; + toppings ~= "Нарезанные черные оливки"; + } +} diff --git a/factorymethod/scheme-1.png b/factorymethod/scheme-1.png new file mode 100644 index 0000000..907ded0 Binary files /dev/null and b/factorymethod/scheme-1.png differ diff --git a/factorymethod/scheme-2.png b/factorymethod/scheme-2.png new file mode 100644 index 0000000..01a06fb Binary files /dev/null and b/factorymethod/scheme-2.png differ diff --git a/factorymethod/scheme-3.png b/factorymethod/scheme-3.png new file mode 100644 index 0000000..ea9882e Binary files /dev/null and b/factorymethod/scheme-3.png differ diff --git a/factorymethod/scheme-4.png b/factorymethod/scheme-4.png new file mode 100644 index 0000000..b904d0a Binary files /dev/null and b/factorymethod/scheme-4.png differ diff --git a/factorymethod/scheme-5.png b/factorymethod/scheme-5.png new file mode 100644 index 0000000..3e60359 Binary files /dev/null and b/factorymethod/scheme-5.png differ diff --git a/factorymethod/scheme-6.png b/factorymethod/scheme-6.png new file mode 100644 index 0000000..dd9ffab Binary files /dev/null and b/factorymethod/scheme-6.png differ 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; + // } +} diff --git a/observer/README.md b/observer/README.md new file mode 100644 index 0000000..145c549 --- /dev/null +++ b/observer/README.md @@ -0,0 +1,16 @@ +# Наблюдатель + +Поведенческий паттерн проектирования, который создаёт механизм подписки, позволяющий одним объектам следить и реагировать на события, происходящие в других объектах. + +При использовании паттерна возможен как [запрос](request/), так и [активная доставка](delivery/) данных от субъекта (запрос считается более "правильным"). + +- **Активная доставка** - передача субъектом аргументов в качестве параметров функции `update()` +- **Запрос** - подразумевает получение необходимых параметров от субъекта внутри функции `update()` + +## Принципы + +- Стремиться к слабой связанности взаимодействующих объектов + +## Схемы + +![scheme-1](scheme-1.png) diff --git a/observer/delivery/app.d b/observer/delivery/app.d new file mode 100644 index 0000000..018c95a --- /dev/null +++ b/observer/delivery/app.d @@ -0,0 +1,22 @@ +module observer.delivery.app; + +import observer.delivery.weatherdata; +import observer.delivery.currentconditionsdisplay; +import observer.delivery.heatindexdisplay; +import observer.delivery.forecastdisplay; +import observer.delivery.statiscticdisplay; + +void main() +{ + WeatherData weatherData = new WeatherData(); + CurrentConditionsDisplay currentDisplay = new CurrentConditionsDisplay(weatherData); + HeatIndexDisplay heatIndexDisplay = new HeatIndexDisplay(weatherData); + ForecastDisplay forecastDisplay = new ForecastDisplay(weatherData); + StatisticsDisplay statisticsDisplay = new StatisticsDisplay(weatherData); + + weatherData.setMeasurements(80, 65, 30.4f); + weatherData.setMeasurements(82, 70, 29.2f); + weatherData.removeObserver(forecastDisplay); + weatherData.setMeasurements(78, 90, 29.2f); + weatherData.setMeasurements(81, 72, 29.5f); +} diff --git a/observer/delivery/currentconditionsdisplay.d b/observer/delivery/currentconditionsdisplay.d new file mode 100644 index 0000000..c020b26 --- /dev/null +++ b/observer/delivery/currentconditionsdisplay.d @@ -0,0 +1,31 @@ +module observer.delivery.currentconditionsdisplay; + +import observer.delivery.displayelement; +import observer.delivery.observer; +import observer.delivery.weatherdata; +import std.stdio : writeln; +import std.format : format; + +class CurrentConditionsDisplay : Observer, DisplayElement +{ +private: + float temperature; + float humidity; +public: + this(WeatherData weatherData) + { + weatherData.registerObserver(this); + } + + override void update(float temperature, float humidity, float pressure) + { + this.temperature = temperature; + this.humidity = humidity; + display(); + } + + override void display() + { + writeln("Current conditions: %3.1f".format(temperature), "F degrees and %3.1f%% humidity".format(humidity)); + } +} diff --git a/observer/delivery/displayelement.d b/observer/delivery/displayelement.d new file mode 100644 index 0000000..7fb8b5b --- /dev/null +++ b/observer/delivery/displayelement.d @@ -0,0 +1,6 @@ +module observer.delivery.displayelement; + +interface DisplayElement +{ + void display(); +} diff --git a/observer/delivery/forecastdisplay.d b/observer/delivery/forecastdisplay.d new file mode 100644 index 0000000..c227136 --- /dev/null +++ b/observer/delivery/forecastdisplay.d @@ -0,0 +1,38 @@ +module observer.delivery.forecastdisplay; + +import observer.delivery.displayelement; +import observer.delivery.observer; +import observer.delivery.weatherdata; +import std.stdio : write, writeln; +import std.format : format; + +class ForecastDisplay : Observer, DisplayElement +{ +private: + float currentPressure = 29.92f; + float lastPressure; +public: + this(WeatherData weatherData) + { + weatherData.registerObserver(this); + } + + override void update(float temperature, float humidity, float pressure) + { + lastPressure = currentPressure; + currentPressure = pressure; + display(); + } + + override void display() + { + write("Forecast: "); + if (currentPressure > lastPressure) { + writeln("Improving weather on the way!"); + } else if (currentPressure == lastPressure) { + writeln("More of the same"); + } else if (currentPressure < lastPressure) { + writeln("Watch out for cooler, rainy weather"); + } + } +} diff --git a/observer/delivery/heatindexdisplay.d b/observer/delivery/heatindexdisplay.d new file mode 100644 index 0000000..38e0329 --- /dev/null +++ b/observer/delivery/heatindexdisplay.d @@ -0,0 +1,38 @@ +module observer.delivery.heatindexdisplay; + +import observer.delivery.displayelement; +import observer.delivery.observer; +import observer.delivery.weatherdata; +import std.stdio : writeln; + +class HeatIndexDisplay : Observer, DisplayElement +{ +private: + float heatIndex; + + float computeHeatIndex(float t, float rh) + { + return ((16.923 + (0.185212 * t) + (5.37941 * rh) - (0.100254 * t * rh) + (0.00941695 * (t * t)) + + (0.00728898 * (rh * rh)) + (0.000345372 * (t * t * rh)) - (0.000814971 * (t * rh * rh)) + + (0.0000102102 * (t * t * rh * rh)) - (0.000038646 * (t * t * t)) + (0.0000291583 * (rh * rh * rh)) + + (0.00000142721 * (t * t * t * rh)) + (0.000000197483 * (t * rh * rh * rh)) + - (0.0000000218429 * (t * t * t * rh * rh)) + 0.000000000843296 * (t * t * rh * rh * rh)) + - (0.0000000000481975 * (t * t * t * rh * rh * rh))); + } +public: + this(WeatherData weatherData) + { + weatherData.registerObserver(this); + } + + override void update(float temperature, float humidity, float pressure) + { + this.heatIndex = computeHeatIndex(temperature, humidity); + display(); + } + + override void display() + { + writeln("Heat index is ", heatIndex); + } +} \ No newline at end of file diff --git a/observer/delivery/observer.d b/observer/delivery/observer.d new file mode 100644 index 0000000..99edfcb --- /dev/null +++ b/observer/delivery/observer.d @@ -0,0 +1,6 @@ +module observer.delivery.observer; + +interface Observer +{ + void update(float temperature, float humidity, float pressure); +} diff --git a/observer/delivery/statiscticdisplay.d b/observer/delivery/statiscticdisplay.d new file mode 100644 index 0000000..a050cd7 --- /dev/null +++ b/observer/delivery/statiscticdisplay.d @@ -0,0 +1,45 @@ +module observer.delivery.statiscticdisplay; + +import observer.delivery.displayelement; +import observer.delivery.observer; +import observer.delivery.weatherdata; +import std.stdio : writeln; +import std.format : format; + +class StatisticsDisplay : Observer, DisplayElement +{ +private: + float maxTemp = 0.0f; + float minTemp = 200; + float tempSum= 0.0f; + int numReadings; +public: + this(WeatherData weatherData) + { + weatherData.registerObserver(this); + } + + override void update(float temperature, float humidity, float pressure) + { + tempSum += temperature; + numReadings++; + + if (temperature > maxTemp) + { + maxTemp = temperature; + } + + if (temperature < minTemp) + { + minTemp = temperature; + } + + display(); + } + + override void display() + { + writeln("Avg/Max/Min temperature = ", (tempSum / numReadings), '/', maxTemp, '/', minTemp); + // writeln("Avg/Max/Min temperature = ".format(temperature), "F degrees and %3.1f%% humidity".format(humidity)); + } +} diff --git a/observer/delivery/subject.d b/observer/delivery/subject.d new file mode 100644 index 0000000..ee48d6f --- /dev/null +++ b/observer/delivery/subject.d @@ -0,0 +1,10 @@ +module observer.delivery.subject; + +import observer.delivery.observer; + +interface Subject +{ + void registerObserver(Observer o); + void removeObserver(Observer o); + void notifyObservers(); +} diff --git a/observer/delivery/weatherdata.d b/observer/delivery/weatherdata.d new file mode 100644 index 0000000..0cd8d32 --- /dev/null +++ b/observer/delivery/weatherdata.d @@ -0,0 +1,60 @@ +module observer.delivery.weatherdata; + +import observer.delivery.subject; +import observer.delivery.observer; +import std.algorithm : remove, countUntil; + +class WeatherData : Subject +{ +private: + Observer[] observers; + float temperature, humidity, pressure; +public: + override void registerObserver(Observer o) + { + observers ~= o; + } + + override void removeObserver(Observer o) + { + // Вызовет ошибку в случае отсутствия элемента в массиве после его поиска + // observers = observers.remove(observers.countUntil(o)); + observers = remove!(current => current == o)(observers); + } + + override void notifyObservers() + { + foreach (Observer o; observers) + { + o.update(temperature, humidity, pressure); + } + } + + void measurementsChanged() + { + notifyObservers(); + } + + void setMeasurements(float temperature, float humidity, float pressure) + { + this.temperature = temperature; + this.humidity = humidity; + this.pressure = pressure; + measurementsChanged(); + } + + @property float getTemperature() + { + return temperature; + } + + @property float getHumidity() + { + return humidity; + } + + @property float getPressure() + { + return pressure; + } +} diff --git a/observer/request/app.d b/observer/request/app.d new file mode 100644 index 0000000..ce04693 --- /dev/null +++ b/observer/request/app.d @@ -0,0 +1,22 @@ +module observer.request.app; + +import observer.request.weatherdata; +import observer.request.currentconditionsdisplay; +import observer.request.heatindexdisplay; +import observer.request.forecastdisplay; +import observer.request.statiscticdisplay; + +void main() +{ + WeatherData weatherData = new WeatherData(); + CurrentConditionsDisplay currentDisplay = new CurrentConditionsDisplay(weatherData); + HeatIndexDisplay heatIndexDisplay = new HeatIndexDisplay(weatherData); + ForecastDisplay forecastDisplay = new ForecastDisplay(weatherData); + StatisticsDisplay statisticsDisplay = new StatisticsDisplay(weatherData); + + weatherData.setMeasurements(80, 65, 30.4f); + weatherData.setMeasurements(82, 70, 29.2f); + weatherData.removeObserver(forecastDisplay); + weatherData.setMeasurements(78, 90, 29.2f); + weatherData.setMeasurements(81, 72, 29.5f); +} diff --git a/observer/request/currentconditionsdisplay.d b/observer/request/currentconditionsdisplay.d new file mode 100644 index 0000000..020099e --- /dev/null +++ b/observer/request/currentconditionsdisplay.d @@ -0,0 +1,33 @@ +module observer.request.currentconditionsdisplay; + +import observer.request.displayelement; +import observer.request.observer; +import observer.request.weatherdata; +import std.stdio : writeln; +import std.format : format; + +class CurrentConditionsDisplay : Observer, DisplayElement +{ +private: + float temperature; + float humidity; + WeatherData weatherData; +public: + this(WeatherData weatherData) + { + this.weatherData = weatherData; + weatherData.registerObserver(this); + } + + override void update() + { + this.temperature = weatherData.getTemperature; + this.humidity = weatherData.getHumidity; + display(); + } + + override void display() + { + writeln("Current conditions: %3.1f".format(temperature), "F degrees and %3.1f%% humidity".format(humidity)); + } +} diff --git a/observer/request/displayelement.d b/observer/request/displayelement.d new file mode 100644 index 0000000..f1b637e --- /dev/null +++ b/observer/request/displayelement.d @@ -0,0 +1,6 @@ +module observer.request.displayelement; + +interface DisplayElement +{ + void display(); +} diff --git a/observer/request/forecastdisplay.d b/observer/request/forecastdisplay.d new file mode 100644 index 0000000..5b07f23 --- /dev/null +++ b/observer/request/forecastdisplay.d @@ -0,0 +1,40 @@ +module observer.request.forecastdisplay; + +import observer.request.displayelement; +import observer.request.observer; +import observer.request.weatherdata; +import std.stdio : write, writeln; +import std.format : format; + +class ForecastDisplay : Observer, DisplayElement +{ +private: + float currentPressure = 29.92f; + float lastPressure; + WeatherData weatherData; +public: + this(WeatherData weatherData) + { + this.weatherData = weatherData; + weatherData.registerObserver(this); + } + + override void update() + { + lastPressure = currentPressure; + currentPressure = weatherData.getPressure; + display(); + } + + override void display() + { + write("Forecast: "); + if (currentPressure > lastPressure) { + writeln("Improving weather on the way!"); + } else if (currentPressure == lastPressure) { + writeln("More of the same"); + } else if (currentPressure < lastPressure) { + writeln("Watch out for cooler, rainy weather"); + } + } +} diff --git a/observer/request/heatindexdisplay.d b/observer/request/heatindexdisplay.d new file mode 100644 index 0000000..7fb84e1 --- /dev/null +++ b/observer/request/heatindexdisplay.d @@ -0,0 +1,40 @@ +module observer.request.heatindexdisplay; + +import observer.request.displayelement; +import observer.request.observer; +import observer.request.weatherdata; +import std.stdio : writeln; + +class HeatIndexDisplay : Observer, DisplayElement +{ +private: + float heatIndex; + WeatherData weatherData; + + float computeHeatIndex(float t, float rh) + { + return ((16.923 + (0.185212 * t) + (5.37941 * rh) - (0.100254 * t * rh) + (0.00941695 * (t * t)) + + (0.00728898 * (rh * rh)) + (0.000345372 * (t * t * rh)) - (0.000814971 * (t * rh * rh)) + + (0.0000102102 * (t * t * rh * rh)) - (0.000038646 * (t * t * t)) + (0.0000291583 * (rh * rh * rh)) + + (0.00000142721 * (t * t * t * rh)) + (0.000000197483 * (t * rh * rh * rh)) + - (0.0000000218429 * (t * t * t * rh * rh)) + 0.000000000843296 * (t * t * rh * rh * rh)) + - (0.0000000000481975 * (t * t * t * rh * rh * rh))); + } +public: + this(WeatherData weatherData) + { + this.weatherData = weatherData; + weatherData.registerObserver(this); + } + + override void update() + { + this.heatIndex = computeHeatIndex(weatherData.getTemperature, weatherData.getHumidity); + display(); + } + + override void display() + { + writeln("Heat index is ", heatIndex); + } +} \ No newline at end of file diff --git a/observer/request/observer.d b/observer/request/observer.d new file mode 100644 index 0000000..0b69040 --- /dev/null +++ b/observer/request/observer.d @@ -0,0 +1,6 @@ +module observer.request.observer; + +interface Observer +{ + void update(); +} diff --git a/observer/request/statiscticdisplay.d b/observer/request/statiscticdisplay.d new file mode 100644 index 0000000..292a698 --- /dev/null +++ b/observer/request/statiscticdisplay.d @@ -0,0 +1,47 @@ +module observer.request.statiscticdisplay; + +import observer.request.displayelement; +import observer.request.observer; +import observer.request.weatherdata; +import std.stdio : writeln; +import std.format : format; + +class StatisticsDisplay : Observer, DisplayElement +{ +private: + float maxTemp = 0.0f; + float minTemp = 200; + float tempSum= 0.0f; + int numReadings; + WeatherData weatherData; +public: + this(WeatherData weatherData) + { + this.weatherData = weatherData; + weatherData.registerObserver(this); + } + + override void update() + { + tempSum += weatherData.getTemperature; + numReadings++; + + if (weatherData.getTemperature > maxTemp) + { + maxTemp = weatherData.getTemperature; + } + + if (weatherData.getTemperature < minTemp) + { + minTemp = weatherData.getTemperature; + } + + display(); + } + + override void display() + { + writeln("Avg/Max/Min temperature = ", (tempSum / numReadings), '/', maxTemp, '/', minTemp); + // writeln("Avg/Max/Min temperature = ".format(temperature), "F degrees and %3.1f%% humidity".format(humidity)); + } +} diff --git a/observer/request/subject.d b/observer/request/subject.d new file mode 100644 index 0000000..822e06e --- /dev/null +++ b/observer/request/subject.d @@ -0,0 +1,10 @@ +module observer.request.subject; + +import observer.request.observer; + +interface Subject +{ + void registerObserver(Observer o); + void removeObserver(Observer o); + void notifyObservers(); +} diff --git a/observer/request/weatherdata.d b/observer/request/weatherdata.d new file mode 100644 index 0000000..32007fa --- /dev/null +++ b/observer/request/weatherdata.d @@ -0,0 +1,60 @@ +module observer.request.weatherdata; + +import observer.request.subject; +import observer.request.observer; +import std.algorithm : remove, countUntil; + +class WeatherData : Subject +{ +private: + Observer[] observers; + float temperature, humidity, pressure; +public: + override void registerObserver(Observer o) + { + observers ~= o; + } + + override void removeObserver(Observer o) + { + // Вызовет ошибку в случае отсутствия элемента в массиве после его поиска + // observers = observers.remove(observers.countUntil(o)); + observers = remove!(current => current == o)(observers); + } + + override void notifyObservers() + { + foreach (Observer o; observers) + { + o.update(); + } + } + + void measurementsChanged() + { + notifyObservers(); + } + + void setMeasurements(float temperature, float humidity, float pressure) + { + this.temperature = temperature; + this.humidity = humidity; + this.pressure = pressure; + measurementsChanged(); + } + + @property float getTemperature() + { + return temperature; + } + + @property float getHumidity() + { + return humidity; + } + + @property float getPressure() + { + return pressure; + } +} diff --git a/observer/scheme-1.png b/observer/scheme-1.png new file mode 100644 index 0000000..1148d89 Binary files /dev/null and b/observer/scheme-1.png differ diff --git a/singleton/README.md b/singleton/README.md new file mode 100644 index 0000000..e08b7a0 --- /dev/null +++ b/singleton/README.md @@ -0,0 +1,7 @@ +# Одиночка + +Порождающий паттерн проектирования, который гарантирует, что у класса есть только один экземпляр, и предоставляет к нему глобальную точку доступа. + +## Схемы + +![scheme-1](scheme-1.png) diff --git a/singleton/app.d b/singleton/app.d new file mode 100644 index 0000000..0d4d126 --- /dev/null +++ b/singleton/app.d @@ -0,0 +1,7 @@ +import singleton.singleton; +import std.stdio : writeln; + +void main() +{ + writeln(Singleton.getInstance().getDescription()); +} diff --git a/singleton/scheme-1.png b/singleton/scheme-1.png new file mode 100644 index 0000000..d3c3ab7 Binary files /dev/null and b/singleton/scheme-1.png differ diff --git a/singleton/singleton.d b/singleton/singleton.d new file mode 100644 index 0000000..d32d07c --- /dev/null +++ b/singleton/singleton.d @@ -0,0 +1,21 @@ +module singleton.singleton; + +class Singleton +{ + private static Singleton singleton; + + private this() {} + + static Singleton getInstance() + { + if (singleton is null) + singleton = new Singleton; + + return singleton; + } + + string getDescription() + { + return "I'm a classic Singleton!"; + } +} diff --git a/state/README.md b/state/README.md new file mode 100644 index 0000000..7b345ee --- /dev/null +++ b/state/README.md @@ -0,0 +1,5 @@ +# Состояние + +Поведенческий паттерн проектирования, который позволяет объектам менять поведение в зависимости от своего состояния. Извне создаётся впечатление, что изменился класс объекта. + +Паттерн **Состояние** управляет изменением поведения объекта при изменении его внутреннего состояния. Внешне это выглядит так, словно объект меняет свой класс. diff --git a/state/gumballmachine/app.d b/state/gumballmachine/app.d new file mode 100644 index 0000000..595958b --- /dev/null +++ b/state/gumballmachine/app.d @@ -0,0 +1,40 @@ +module app; + +import gumballmachine; +import std.stdio : writeln; + +void main() +{ + GumballMachine gumballMachine = new GumballMachine(5); + + writeln(gumballMachine); + + gumballMachine.insertQuarter(); + gumballMachine.turnCrank(); + + writeln(gumballMachine); + + gumballMachine.insertQuarter(); + gumballMachine.ejectQuarter(); + gumballMachine.turnCrank(); + + writeln(gumballMachine); + + gumballMachine.insertQuarter(); + gumballMachine.turnCrank(); + gumballMachine.insertQuarter(); + gumballMachine.turnCrank(); + gumballMachine.ejectQuarter(); + + writeln(gumballMachine); + + gumballMachine.insertQuarter(); + gumballMachine.insertQuarter(); + gumballMachine.turnCrank(); + gumballMachine.insertQuarter(); + gumballMachine.turnCrank(); + gumballMachine.insertQuarter(); + gumballMachine.turnCrank(); + + writeln(gumballMachine); +} diff --git a/state/gumballmachine/gumballmachine.d b/state/gumballmachine/gumballmachine.d new file mode 100644 index 0000000..8a4d30b --- /dev/null +++ b/state/gumballmachine/gumballmachine.d @@ -0,0 +1,155 @@ +module gumballmachine; + +import std.stdio : writeln; +import std.conv : to; + +class GumballMachine +{ + static const int SOLD_OUT = 0; // нет шариков + static const int NO_QUARTER = 1; // нет монетки + static const int HAS_QUARTER = 2; // есть монетка + static const int SOLD = 3; // шарик продан + + int state = SOLD_OUT; + int count = 0; + + this(int count) + { + this.count = count; + if (count > 0) + { + state = NO_QUARTER; + } + } + + void insertQuarter() + { + if (state == HAS_QUARTER) + { + writeln("You can't insert another quarter"); + } + else if (state == NO_QUARTER) + { + state = HAS_QUARTER; + writeln("You inserted a quarter"); + } + else if (state == SOLD_OUT) + { + writeln("You can't insert a quarter, the machine is sold out"); + } + else if (state == SOLD) + { + writeln("Please wait, we're already giving you a gumball"); + } + } + + void ejectQuarter() + { + if (state == HAS_QUARTER) + { + writeln("Quarter returned"); + state = NO_QUARTER; + } + else if (state == NO_QUARTER) + { + writeln("You haven't inserted a quarter"); + } + else if (state == SOLD) + { + writeln("Sorry, you already turned the crank"); + } + else if (state == SOLD_OUT) + { + writeln("You can't eject, you haven't inserted a quarter yet"); + } + } + + void turnCrank() + { + if (state == SOLD) + { + writeln("Turning twice doesn't get you another gumball!"); + } + else if (state == NO_QUARTER) + { + writeln("You turned but there's no quarter"); + } + else if (state == SOLD_OUT) + { + writeln("You turned, but there are no gumballs"); + } + else if (state == HAS_QUARTER) + { + writeln("You turned..."); + state = SOLD; + dispense(); + } + } + + private void dispense() + { + if (state == SOLD) + { + writeln("A gumball comes rolling out the slot"); + --count; + if (count == 0) + { + writeln("Oops, out of gumballs!"); + state = SOLD_OUT; + } + else + { + state = NO_QUARTER; + } + } + else if (state == NO_QUARTER) + { + writeln("You need to pay first"); + } + else if (state == SOLD_OUT) + { + writeln("No gumball dispensed"); + } + else if (state == HAS_QUARTER) + { + writeln("No gumball dispensed"); + } + } + + void refill(int numGumBalls) + { + this.count = numGumBalls; + state = NO_QUARTER; + } + + override string toString() const + { + string s; + s ~= "\nMighty Gumball, Inc."; + s ~= "\nJava-enabled Standing Gumball Model #2004\n"; + s ~= "Inventory: " ~ count.to!string ~ " gumball"; + if (count != 1) + { + s ~= "s"; + } + s ~= "\nMachine is "; + if (state == SOLD_OUT) + { + s ~= "sold out"; + } + else if (state == NO_QUARTER) + { + s ~= "waiting for quarter"; + } + else if (state == HAS_QUARTER) + { + s ~= "waiting for turn of crank"; + } + else if (state == SOLD) + { + s ~= "delivering a gumball"; + } + s ~= "\n"; + return s; + } +} diff --git a/state/gumballmachinestate/app.d b/state/gumballmachinestate/app.d new file mode 100644 index 0000000..43272c0 --- /dev/null +++ b/state/gumballmachinestate/app.d @@ -0,0 +1,27 @@ +module app; + +import gumballmachine; +import std.stdio : writeln; + +void main() +{ + GumballMachine gumballMachine = new GumballMachine(2); + + writeln(gumballMachine); + + gumballMachine.insertQuarter(); + gumballMachine.turnCrank(); + + writeln(gumballMachine); + + gumballMachine.insertQuarter(); + gumballMachine.turnCrank(); + gumballMachine.insertQuarter(); + gumballMachine.turnCrank(); + + gumballMachine.refill(5); + gumballMachine.insertQuarter(); + gumballMachine.turnCrank(); + + writeln(gumballMachine); +} diff --git a/state/gumballmachinestate/gumballmachine.d b/state/gumballmachinestate/gumballmachine.d new file mode 100644 index 0000000..479b40e --- /dev/null +++ b/state/gumballmachinestate/gumballmachine.d @@ -0,0 +1,117 @@ +module gumballmachine; + +import std.stdio : writeln; +import std.conv : to; +import soldoutstate, noquarterstate, hasquarterstate, soldstate, state; + +class GumballMachine +{ + State soldOutState; // нет жевательных шариков + State noQuarterState; // нет четвертака (есть жевательные шарики, готов к продаже) + State hasQuarterState; // вставлен четвертак (либо купить шарик, либо вернуть моентку) + State soldState; // продажа шарика (выдача шарика) + + State state; + int count = 0; + + this(int numberGumballs) + { + soldOutState = new SoldOutState(this); + noQuarterState = new NoQuarterState(this); + hasQuarterState = new HasQuarterState(this); + soldState = new SoldState(this); + + this.count = numberGumballs; + if (numberGumballs > 0) + { + state = noQuarterState; + } + else + { + state = soldOutState; + } + } + + void insertQuarter() + { + state.insertQuarter(); + } + + void ejectQuarter() + { + state.ejectQuarter(); + } + + void turnCrank() + { + state.turnCrank(); + state.dispense(); + } + + void releaseBall() + { + writeln("Из щели выкатывается шарик жевательной резинки..."); + if (count > 0) + { + count = count - 1; + } + } + + int getCount() + { + return count; + } + + void refill(int count) + { + this.count += count; + writeln("Автомат для жевательных резинок был только что заправлен; его новое количество составляет: ", + this.count); + state.refill(); + } + + void setState(State state) + { + this.state = state; + } + + State getState() + { + return state; + } + + State getSoldOutState() + { + return soldOutState; + } + + State getNoQuarterState() + { + return noQuarterState; + } + + State getHasQuarterState() + { + return hasQuarterState; + } + + State getSoldState() + { + return soldState; + } + + override string toString() const + { + string s; + s ~= "\nMighty Gumball, Inc."; + s ~= "\nD-enabled Standing Gumball Model #2004"; + s ~= "\nInventory: " ~ count.to!string ~ " gumball"; + if (count != 1) + { + s ~= "s"; + } + s ~= "\n"; + s ~= "Machine is " ~ state.to!string ~ "\n"; + return s; + } +} \ No newline at end of file diff --git a/state/gumballmachinestate/hasquarterstate.d b/state/gumballmachinestate/hasquarterstate.d new file mode 100644 index 0000000..89124a1 --- /dev/null +++ b/state/gumballmachinestate/hasquarterstate.d @@ -0,0 +1,43 @@ +module hasquarterstate; + +import std.stdio : writeln; +import state, gumballmachine; + +class HasQuarterState : State +{ + GumballMachine gumballMachine; + + this(GumballMachine gumballMachine) + { + this.gumballMachine = gumballMachine; + } + + void insertQuarter() + { + writeln("Вы не можете вставить еще один четвертак"); + } + + void ejectQuarter() + { + writeln("Четвертак возвращен"); + gumballMachine.setState(gumballMachine.getNoQuarterState()); + } + + void turnCrank() + { + writeln("Вы дернули за рычаг..."); + gumballMachine.setState(gumballMachine.getSoldState()); + } + + void dispense() + { + writeln("Жевательная резинка не выдается"); + } + + void refill() {} + + override string toString() const + { + return "ожидание поворота рычага"; + } +} \ No newline at end of file diff --git a/state/gumballmachinestate/noquarterstate.d b/state/gumballmachinestate/noquarterstate.d new file mode 100644 index 0000000..3eec142 --- /dev/null +++ b/state/gumballmachinestate/noquarterstate.d @@ -0,0 +1,42 @@ +module noquarterstate; + +import std.stdio : writeln; +import state, gumballmachine; + +class NoQuarterState : State +{ + GumballMachine gumballMachine; + + this(GumballMachine gumballMachine) + { + this.gumballMachine = gumballMachine; + } + + void insertQuarter() + { + writeln("Вы вставили четвертак"); + gumballMachine.setState(gumballMachine.getHasQuarterState()); + } + + void ejectQuarter() + { + writeln("Вы не вставили четвертак"); + } + + void turnCrank() + { + writeln("Вы дернули за рычаг, но нет четвертака"); + } + + void dispense() + { + writeln("Сначала вам нужно заплатить"); + } + + void refill() { } + + override string toString() const + { + return "в ожидании четвертака"; + } +} \ No newline at end of file diff --git a/state/gumballmachinestate/soldoutstate.d b/state/gumballmachinestate/soldoutstate.d new file mode 100644 index 0000000..53ac965 --- /dev/null +++ b/state/gumballmachinestate/soldoutstate.d @@ -0,0 +1,44 @@ +module soldoutstate; + +import std.stdio : writeln; +import state, gumballmachine; + +class SoldOutState : State +{ + GumballMachine gumballMachine; + + this(GumballMachine gumballMachine) + { + this.gumballMachine = gumballMachine; + } + + void insertQuarter() + { + writeln("Вы не можете вставить четвертак, машина распродана"); + } + + void ejectQuarter() + { + writeln("Вы не можете извлечь, вы еще не вставили четвертак"); + } + + void turnCrank() + { + writeln("Вы дернули за рычаг, но там нет жевательных шариков"); + } + + void dispense() + { + writeln("Жевательная резинка не выдается"); + } + + void refill() + { + gumballMachine.setState(gumballMachine.getNoQuarterState()); + } + + override string toString() const + { + return "продано"; + } +} diff --git a/state/gumballmachinestate/soldstate.d b/state/gumballmachinestate/soldstate.d new file mode 100644 index 0000000..8fb1154 --- /dev/null +++ b/state/gumballmachinestate/soldstate.d @@ -0,0 +1,50 @@ +module soldstate; + +import std.stdio : writeln; +import state, gumballmachine; + +class SoldState : State +{ + GumballMachine gumballMachine; + + this(GumballMachine gumballMachine) + { + this.gumballMachine = gumballMachine; + } + + void insertQuarter() + { + writeln("Пожалуйста, подождите, мы уже даем вам жвачку"); + } + + void ejectQuarter() + { + writeln("Извините, вы уже дернули за рычаг"); + } + + void turnCrank() + { + writeln("Дважды дернув за рычаг вы не получите другую жвачку!"); + } + + void dispense() + { + gumballMachine.releaseBall(); + if (gumballMachine.getCount() > 0) + { + gumballMachine.setState(gumballMachine.getNoQuarterState()); + } + else + { + writeln("Упс, кончились жевательные шарики!"); + gumballMachine.setState(gumballMachine.getSoldOutState()); + } + } + + void refill() {} + + override string toString() const + { + return "раздача жевательной резинки"; + } +} \ No newline at end of file diff --git a/state/gumballmachinestate/state.d b/state/gumballmachinestate/state.d new file mode 100644 index 0000000..813481d --- /dev/null +++ b/state/gumballmachinestate/state.d @@ -0,0 +1,11 @@ +module state; + +interface State +{ + void insertQuarter(); + void ejectQuarter(); + void turnCrank(); + void dispense(); + + void refill(); +} diff --git a/state/gumballmachinewinnerstate/app.d b/state/gumballmachinewinnerstate/app.d new file mode 100644 index 0000000..26f6d89 --- /dev/null +++ b/state/gumballmachinewinnerstate/app.d @@ -0,0 +1,46 @@ +module app; + +import gumballmachine; +import std.stdio : writeln; + +void main() +{ + GumballMachine gumballMachine = new GumballMachine(10); + + writeln(gumballMachine); + + gumballMachine.insertQuarter(); + gumballMachine.turnCrank(); + gumballMachine.insertQuarter(); + gumballMachine.turnCrank(); + + writeln(gumballMachine); + + gumballMachine.insertQuarter(); + gumballMachine.turnCrank(); + gumballMachine.insertQuarter(); + gumballMachine.turnCrank(); + + writeln(gumballMachine); + + gumballMachine.insertQuarter(); + gumballMachine.turnCrank(); + gumballMachine.insertQuarter(); + gumballMachine.turnCrank(); + + writeln(gumballMachine); + + gumballMachine.insertQuarter(); + gumballMachine.turnCrank(); + gumballMachine.insertQuarter(); + gumballMachine.turnCrank(); + + writeln(gumballMachine); + + gumballMachine.insertQuarter(); + gumballMachine.turnCrank(); + gumballMachine.insertQuarter(); + gumballMachine.turnCrank(); + + writeln(gumballMachine); +} diff --git a/state/gumballmachinewinnerstate/gumballmachine.d b/state/gumballmachinewinnerstate/gumballmachine.d new file mode 100644 index 0000000..4ede1bc --- /dev/null +++ b/state/gumballmachinewinnerstate/gumballmachine.d @@ -0,0 +1,124 @@ +module gumballmachine; + +import std.stdio : writeln; +import std.conv : to; +import soldoutstate, noquarterstate, hasquarterstate, soldstate, state, winnerstate; + +class GumballMachine +{ + State soldOutState; // нет жевательных шариков + State noQuarterState; // нет четвертака (есть жевательные шарики, готов к продаже) + State hasQuarterState; // вставлен четвертак (либо купить шарик, либо вернуть моентку) + State soldState; // продажа шарика (выдача шарика) + State winnerState; // выдача дополнительного шарика при 10% вероятности + + State state; + int count = 0; + + this(int numberGumballs) + { + soldOutState = new SoldOutState(this); + noQuarterState = new NoQuarterState(this); + hasQuarterState = new HasQuarterState(this); + soldState = new SoldState(this); + winnerState = new WinnerState(this); + + this.count = numberGumballs; + if (numberGumballs > 0) + { + state = noQuarterState; + } + else + { + state = soldOutState; + } + } + + void insertQuarter() + { + state.insertQuarter(); + } + + void ejectQuarter() + { + state.ejectQuarter(); + } + + void turnCrank() + { + state.turnCrank(); + state.dispense(); + } + + void releaseBall() + { + writeln("Из щели выкатывается шарик жевательной резинки..."); + if (count > 0) + { + count = count - 1; + } + } + + int getCount() + { + return count; + } + + void refill(int count) + { + this.count += count; + writeln("Автомат для жевательных резинок был только что заправлен; его новое количество составляет: ", + this.count); + state.refill(); + } + + void setState(State state) + { + this.state = state; + } + + State getState() + { + return state; + } + + State getSoldOutState() + { + return soldOutState; + } + + State getNoQuarterState() + { + return noQuarterState; + } + + State getHasQuarterState() + { + return hasQuarterState; + } + + State getSoldState() + { + return soldState; + } + + State getWinnerState() + { + return winnerState; + } + + override string toString() const + { + string s; + s ~= "\nMighty Gumball, Inc."; + s ~= "\nD-enabled Standing Gumball Model #2004"; + s ~= "\nInventory: " ~ count.to!string ~ " gumball"; + if (count != 1) + { + s ~= "s"; + } + s ~= "\n"; + s ~= "Machine is " ~ state.to!string ~ "\n"; + return s; + } +} \ No newline at end of file diff --git a/state/gumballmachinewinnerstate/hasquarterstate.d b/state/gumballmachinewinnerstate/hasquarterstate.d new file mode 100644 index 0000000..8e6bf16 --- /dev/null +++ b/state/gumballmachinewinnerstate/hasquarterstate.d @@ -0,0 +1,53 @@ +module hasquarterstate; + +import std.stdio : writeln; +import std.random : Random, uniform, unpredictableSeed; +import state, gumballmachine; + +class HasQuarterState : State +{ + GumballMachine gumballMachine; + Random randomWinner; + + this(GumballMachine gumballMachine) + { + this.gumballMachine = gumballMachine; + randomWinner = Random(unpredictableSeed); + } + + void insertQuarter() + { + writeln("Вы не можете вставить еще один четвертак"); + } + + void ejectQuarter() + { + writeln("Четвертак возвращен"); + gumballMachine.setState(gumballMachine.getNoQuarterState()); + } + + void turnCrank() + { + writeln("Вы дернули за рычаг..."); + if ((uniform(0, 10, randomWinner) == 0) && (gumballMachine.getCount() > 1)) + { + gumballMachine.setState(gumballMachine.getWinnerState()); + } + else + { + gumballMachine.setState(gumballMachine.getSoldState()); + } + } + + void dispense() + { + writeln("Жевательная резинка не выдается"); + } + + void refill() {} + + override string toString() const + { + return "ожидание поворота рычага"; + } +} \ No newline at end of file diff --git a/state/gumballmachinewinnerstate/noquarterstate.d b/state/gumballmachinewinnerstate/noquarterstate.d new file mode 100644 index 0000000..3eec142 --- /dev/null +++ b/state/gumballmachinewinnerstate/noquarterstate.d @@ -0,0 +1,42 @@ +module noquarterstate; + +import std.stdio : writeln; +import state, gumballmachine; + +class NoQuarterState : State +{ + GumballMachine gumballMachine; + + this(GumballMachine gumballMachine) + { + this.gumballMachine = gumballMachine; + } + + void insertQuarter() + { + writeln("Вы вставили четвертак"); + gumballMachine.setState(gumballMachine.getHasQuarterState()); + } + + void ejectQuarter() + { + writeln("Вы не вставили четвертак"); + } + + void turnCrank() + { + writeln("Вы дернули за рычаг, но нет четвертака"); + } + + void dispense() + { + writeln("Сначала вам нужно заплатить"); + } + + void refill() { } + + override string toString() const + { + return "в ожидании четвертака"; + } +} \ No newline at end of file diff --git a/state/gumballmachinewinnerstate/soldoutstate.d b/state/gumballmachinewinnerstate/soldoutstate.d new file mode 100644 index 0000000..53ac965 --- /dev/null +++ b/state/gumballmachinewinnerstate/soldoutstate.d @@ -0,0 +1,44 @@ +module soldoutstate; + +import std.stdio : writeln; +import state, gumballmachine; + +class SoldOutState : State +{ + GumballMachine gumballMachine; + + this(GumballMachine gumballMachine) + { + this.gumballMachine = gumballMachine; + } + + void insertQuarter() + { + writeln("Вы не можете вставить четвертак, машина распродана"); + } + + void ejectQuarter() + { + writeln("Вы не можете извлечь, вы еще не вставили четвертак"); + } + + void turnCrank() + { + writeln("Вы дернули за рычаг, но там нет жевательных шариков"); + } + + void dispense() + { + writeln("Жевательная резинка не выдается"); + } + + void refill() + { + gumballMachine.setState(gumballMachine.getNoQuarterState()); + } + + override string toString() const + { + return "продано"; + } +} diff --git a/state/gumballmachinewinnerstate/soldstate.d b/state/gumballmachinewinnerstate/soldstate.d new file mode 100644 index 0000000..8fb1154 --- /dev/null +++ b/state/gumballmachinewinnerstate/soldstate.d @@ -0,0 +1,50 @@ +module soldstate; + +import std.stdio : writeln; +import state, gumballmachine; + +class SoldState : State +{ + GumballMachine gumballMachine; + + this(GumballMachine gumballMachine) + { + this.gumballMachine = gumballMachine; + } + + void insertQuarter() + { + writeln("Пожалуйста, подождите, мы уже даем вам жвачку"); + } + + void ejectQuarter() + { + writeln("Извините, вы уже дернули за рычаг"); + } + + void turnCrank() + { + writeln("Дважды дернув за рычаг вы не получите другую жвачку!"); + } + + void dispense() + { + gumballMachine.releaseBall(); + if (gumballMachine.getCount() > 0) + { + gumballMachine.setState(gumballMachine.getNoQuarterState()); + } + else + { + writeln("Упс, кончились жевательные шарики!"); + gumballMachine.setState(gumballMachine.getSoldOutState()); + } + } + + void refill() {} + + override string toString() const + { + return "раздача жевательной резинки"; + } +} \ No newline at end of file diff --git a/state/gumballmachinewinnerstate/state.d b/state/gumballmachinewinnerstate/state.d new file mode 100644 index 0000000..813481d --- /dev/null +++ b/state/gumballmachinewinnerstate/state.d @@ -0,0 +1,11 @@ +module state; + +interface State +{ + void insertQuarter(); + void ejectQuarter(); + void turnCrank(); + void dispense(); + + void refill(); +} diff --git a/state/gumballmachinewinnerstate/winnerstate.d b/state/gumballmachinewinnerstate/winnerstate.d new file mode 100644 index 0000000..51d1d18 --- /dev/null +++ b/state/gumballmachinewinnerstate/winnerstate.d @@ -0,0 +1,59 @@ +module winnerstate; + +import std.stdio : writeln; +import state, gumballmachine; + +class WinnerState : State +{ + GumballMachine gumballMachine; + + this(GumballMachine gumballMachine) + { + this.gumballMachine = gumballMachine; + } + + void insertQuarter() + { + writeln("Пожалуйста, подождите, мы уже даем вам жвачку"); + } + + void ejectQuarter() + { + writeln("Пожалуйста, подождите, мы уже даем вам жвачку"); + } + + void turnCrank() + { + writeln("Дважды дернув за рычаг вы не получите другую жвачку!"); + } + + void dispense() + { + gumballMachine.releaseBall(); + if (gumballMachine.getCount() == 0) + { + gumballMachine.setState(gumballMachine.getSoldOutState()); + } + else + { + gumballMachine.releaseBall(); + writeln("ТЫ ПОБЕДИТЕЛЬ! У тебя есть два жевательных шарика на твой четвертак"); + if (gumballMachine.getCount() > 0) + { + gumballMachine.setState(gumballMachine.getNoQuarterState()); + } + else + { + writeln("Упс, кончились шарики!"); + gumballMachine.setState(gumballMachine.getSoldOutState()); + } + } + } + + void refill() {} + + override string toString() const + { + return "раздаем два жевательных шарика за твою четвертак, потому что ТЫ ПОБЕДИТЕЛЬ!"; + } +} diff --git a/strategy/README.md b/strategy/README.md new file mode 100644 index 0000000..8c2b8fb --- /dev/null +++ b/strategy/README.md @@ -0,0 +1,19 @@ +# Стратегия + +Поведенческий паттерн проектирования, который определяет семейство схожих алгоритмов и помещает каждый из них в собственный класс, после чего алгоритмы можно взаимозаменять прямо во время исполнения программы. + +Инкапсуляция алгоритма в объект — это назначение паттерна **Стратегия**. Использует композицию. Определяет семейство алгоритмов и обеспечивает их взаимозаменяемость. Инкапсуляция позволяет легко использовать разные алгоритмы на стороне клиента. + +## Код + +Каждая утка СОДЕРЖИТ экземпляры `FlyBehavior` и `Quack­Behavior`, которым делегируются выполнение соответствующих операций. Подобные связи между двумя классами означают, что используется механизм композиции. Поведение не наследуется, а предоставляется правильно выбранным объектом. + +## Принципы + +- Инкапсулировать то, что изменяется +- Отдавать предпочтение композиции перед наследованием +- Программировать на уровне интерфейсов, а не реализации + +## Схемы + +![scheme-1](scheme-1.png) diff --git a/strategy/app.d b/strategy/app.d new file mode 100644 index 0000000..ef3e518 --- /dev/null +++ b/strategy/app.d @@ -0,0 +1,17 @@ +module strategy.app; + +import strategy.duck; +import strategy.flybehavior; + +void main() +{ + Duck mallard = new MallardDuck; + mallard.performQuack(); + mallard.performFly(); + + Duck model = new ModelDuck; + model.performQuack(); + model.performFly(); + model.setFlyBehavior(new FlyRocketPowered); + model.performFly(); +} diff --git a/strategy/duck.d b/strategy/duck.d new file mode 100644 index 0000000..76a0398 --- /dev/null +++ b/strategy/duck.d @@ -0,0 +1,66 @@ +module strategy.duck; + +import strategy.flybehavior; +import strategy.quackbehavior; +import std.stdio : writeln; + +abstract class Duck +{ + FlyBehavior flyBehavior; + QuackBehavior quackBehavior; + + void display(); + + void performFly() + { + flyBehavior.fly(); + } + + void performQuack() + { + quackBehavior.quack(); + } + + void swim() + { + writeln("All ducks float, even decoys!"); + } + + void setFlyBehavior(FlyBehavior fb) + { + flyBehavior = fb; + } + + void setQuackBehavior(QuackBehavior qb) + { + quackBehavior = qb; + } +} + +class MallardDuck : Duck +{ + this() + { + quackBehavior = new Quack; + flyBehavior = new FlyWithWings; + } + + override void display() + { + writeln("I'm a real Mallard duck"); + } +} + +class ModelDuck : Duck +{ + this() + { + quackBehavior = new Squeak; + flyBehavior = new FlyNoWay; + } + + override void display() + { + writeln("I'm a model duck"); + } +} diff --git a/strategy/flybehavior.d b/strategy/flybehavior.d new file mode 100644 index 0000000..1ca123b --- /dev/null +++ b/strategy/flybehavior.d @@ -0,0 +1,32 @@ +module strategy.flybehavior; + +import std.stdio : writeln; + +abstract interface FlyBehavior +{ + void fly(); +} + +class FlyWithWings : FlyBehavior +{ + override void fly() + { + writeln("I'm flying!"); + } +} + +class FlyNoWay : FlyBehavior +{ + override void fly() + { + writeln("I can't fly"); + } +} + +class FlyRocketPowered : FlyBehavior +{ + override void fly() + { + writeln("I'm flying with a rocket!"); + } +} diff --git a/strategy/quackbehavior.d b/strategy/quackbehavior.d new file mode 100644 index 0000000..c2f2e28 --- /dev/null +++ b/strategy/quackbehavior.d @@ -0,0 +1,32 @@ +module strategy.quackbehavior; + +import std.stdio : writeln; + +abstract interface QuackBehavior +{ + void quack(); +} + +class Quack : QuackBehavior +{ + override void quack() + { + writeln("Quack"); + } +} + +class Squeak : QuackBehavior +{ + override void quack() + { + writeln("Squeak"); + } +} + +class MuteQuack : QuackBehavior +{ + override void quack() + { + writeln("Silence"); + } +} diff --git a/strategy/scheme-1.png b/strategy/scheme-1.png new file mode 100644 index 0000000..9cb0766 Binary files /dev/null and b/strategy/scheme-1.png differ diff --git a/templatemethod/README.md b/templatemethod/README.md new file mode 100644 index 0000000..9a81274 --- /dev/null +++ b/templatemethod/README.md @@ -0,0 +1,23 @@ +# Шаблонный метод + +Поведенческий паттерн проектирования, который определяет скелет алгоритма, перекладывая ответственность за некоторые его шаги на подклассы. Паттерн позволяет подклассам переопределять шаги алгоритма, не меняя его общей структуры. + +Паттерн **Шаблонный Метод** задает «скелет» алгоритма в методе, оставляя определение реализации некоторых шагов субклассам. Субклассы могут переопределять некоторые части алгоритма без изменения его структуры. + +## Принципы + +- Не вызывайте нас - мы вас сами вызовем + +Алгоритм определяется суперклассом, поэтому последний должен сам обращаться к субклассам, когда потребуется. + +## Схемы + +![scheme-1](scheme-1.png) + +![scheme-2](scheme-2.png) + +![scheme-3](scheme-3.png) + +![scheme-4](scheme-4.png) + +![scheme-5](scheme-5.png) diff --git a/templatemethod/barista/app.d b/templatemethod/barista/app.d new file mode 100644 index 0000000..860d360 --- /dev/null +++ b/templatemethod/barista/app.d @@ -0,0 +1,21 @@ +import std.stdio : writeln; +import coffee, tea, coffeewithhook, teawithhook; + +void main() +{ + auto tea = new Tea(); + auto coffee = new Coffee(); + + writeln("\nMaking tea..."); + tea.prepareRecipe(); + writeln("\nMaking coffee..."); + coffee.prepareRecipe(); + + auto teaHook = new TeaWithHook(); + auto coffeeHook = new CoffeeWithHook(); + + writeln("\nMaking tea..."); + teaHook.prepareRecipe(); + writeln("\nMaking coffee..."); + coffeeHook.prepareRecipe(); +} diff --git a/templatemethod/barista/caffeinebeverage.d b/templatemethod/barista/caffeinebeverage.d new file mode 100644 index 0000000..a464abf --- /dev/null +++ b/templatemethod/barista/caffeinebeverage.d @@ -0,0 +1,28 @@ +module caffeinebeverage; + +import std.stdio : writeln; + +abstract class CaffeineBeverage +{ + final void prepareRecipe() + { + boilWater(); + brew(); + pourInCup(); + addCondiments(); + } + + void brew(); + + void addCondiments(); + + void boilWater() + { + writeln("Boiling water"); + } + + void pourInCup() + { + writeln("Pouring into cup"); + } +} diff --git a/templatemethod/barista/caffeinebeveragewithhook.d b/templatemethod/barista/caffeinebeveragewithhook.d new file mode 100644 index 0000000..1541570 --- /dev/null +++ b/templatemethod/barista/caffeinebeveragewithhook.d @@ -0,0 +1,36 @@ +module caffeinebeveragewithhook; + +import std.stdio : writeln; + +abstract class CaffeineBeverageWithHook +{ + final void prepareRecipe() + { + boilWater(); + brew(); + pourInCup(); + if (customerWantsCondiments()) + { + addCondiments(); + } + } + + void brew(); + + void addCondiments(); + + void boilWater() + { + writeln("Boiling water"); + } + + void pourInCup() + { + writeln("Pouring into cup"); + } + + bool customerWantsCondiments() + { + return true; + } +} diff --git a/templatemethod/barista/coffee.d b/templatemethod/barista/coffee.d new file mode 100644 index 0000000..d44d520 --- /dev/null +++ b/templatemethod/barista/coffee.d @@ -0,0 +1,17 @@ +module coffee; + +import std.stdio : writeln; +import caffeinebeverage; + +class Coffee : CaffeineBeverage +{ + override void brew() + { + writeln("Dripping Coffee through filter"); + } + + override void addCondiments() + { + writeln("Adding Sugar and Milk"); + } +} diff --git a/templatemethod/barista/coffeewithhook.d b/templatemethod/barista/coffeewithhook.d new file mode 100644 index 0000000..330f260 --- /dev/null +++ b/templatemethod/barista/coffeewithhook.d @@ -0,0 +1,45 @@ +module coffeewithhook; + +import std.stdio : write, writeln, readln; +import std.uni : toLower; +import std.algorithm : startsWith; +import caffeinebeveragewithhook; + +class CoffeeWithHook : CaffeineBeverageWithHook +{ + override void brew() + { + writeln("Dripping Coffee through filter"); + } + + override void addCondiments() + { + writeln("Adding Sugar and Milk"); + } + + override bool customerWantsCondiments() + { + if (getUserInput().toLower().startsWith("y")) + { + return true; + } + else + { + return false; + } + } + + string getUserInput() + { + string answer; + + write("Would you like milk and sugar with your coffee (y/n)? "); + + if ((answer = readln()) !is null) + { + return answer; + } + + return "no"; + } +} diff --git a/templatemethod/barista/tea.d b/templatemethod/barista/tea.d new file mode 100644 index 0000000..13fdc10 --- /dev/null +++ b/templatemethod/barista/tea.d @@ -0,0 +1,17 @@ +module tea; + +import std.stdio : writeln; +import caffeinebeverage; + +class Tea : CaffeineBeverage +{ + override void brew() + { + writeln("Steeping the tea"); + } + + override void addCondiments() + { + writeln("Adding Lemon"); + } +} diff --git a/templatemethod/barista/teawithhook.d b/templatemethod/barista/teawithhook.d new file mode 100644 index 0000000..f521994 --- /dev/null +++ b/templatemethod/barista/teawithhook.d @@ -0,0 +1,45 @@ +module teawithhook; + +import std.stdio : write, writeln, readln; +import std.uni : toLower; +import std.algorithm : startsWith; +import caffeinebeveragewithhook; + +class TeaWithHook : CaffeineBeverageWithHook +{ + override void brew() + { + writeln("Steeping the tea"); + } + + override void addCondiments() + { + writeln("Adding Lemon"); + } + + override bool customerWantsCondiments() + { + if (getUserInput().toLower().startsWith("y")) + { + return true; + } + else + { + return false; + } + } + + string getUserInput() + { + string answer; + + write("Would you like lemon with your tea (y/n)? "); + + if ((answer = readln()) !is null) + { + return answer; + } + + return "no"; + } +} diff --git a/templatemethod/scheme-1.png b/templatemethod/scheme-1.png new file mode 100644 index 0000000..5aae44f Binary files /dev/null and b/templatemethod/scheme-1.png differ diff --git a/templatemethod/scheme-2.png b/templatemethod/scheme-2.png new file mode 100644 index 0000000..82933e1 Binary files /dev/null and b/templatemethod/scheme-2.png differ diff --git a/templatemethod/scheme-3.png b/templatemethod/scheme-3.png new file mode 100644 index 0000000..725481b Binary files /dev/null and b/templatemethod/scheme-3.png differ diff --git a/templatemethod/scheme-4.png b/templatemethod/scheme-4.png new file mode 100644 index 0000000..6a2888a Binary files /dev/null and b/templatemethod/scheme-4.png differ diff --git a/templatemethod/scheme-5.png b/templatemethod/scheme-5.png new file mode 100644 index 0000000..31c3699 Binary files /dev/null and b/templatemethod/scheme-5.png differ diff --git a/templatemethod/simplebarista/app.d b/templatemethod/simplebarista/app.d new file mode 100644 index 0000000..95c51f0 --- /dev/null +++ b/templatemethod/simplebarista/app.d @@ -0,0 +1,12 @@ +import std.stdio : writeln; +import coffee, tea; + +void main() +{ + auto tea = new Tea(); + auto coffee = new Coffee(); + writeln("Making tea..."); + tea.prepareRecipe(); + writeln("Making coffee..."); + coffee.prepareRecipe(); +} diff --git a/templatemethod/simplebarista/coffee.d b/templatemethod/simplebarista/coffee.d new file mode 100644 index 0000000..7b9fc26 --- /dev/null +++ b/templatemethod/simplebarista/coffee.d @@ -0,0 +1,34 @@ +module coffee; + +import std.stdio : writeln; + +class Coffee +{ + void prepareRecipe() + { + boilWater(); + brewCoffeeGrinds(); + pourInCup(); + addSugarAndMilk(); + } + + void boilWater() + { + writeln("Boiling water"); + } + + void brewCoffeeGrinds() + { + writeln("Dripping Coffee through filter"); + } + + void pourInCup() + { + writeln("Pouring into cup"); + } + + void addSugarAndMilk() + { + writeln("Adding Sugar and Milk"); + } +} diff --git a/templatemethod/simplebarista/tea.d b/templatemethod/simplebarista/tea.d new file mode 100644 index 0000000..ca55a68 --- /dev/null +++ b/templatemethod/simplebarista/tea.d @@ -0,0 +1,34 @@ +module tea; + +import std.stdio : writeln; + +class Tea +{ + void prepareRecipe() + { + boilWater(); + steepTeaBag(); + pourInCup(); + addLemon(); + } + + void boilWater() + { + writeln("Boiling water"); + } + + void steepTeaBag() + { + writeln("Steeping the tea"); + } + + void addLemon() + { + writeln("Adding Lemon"); + } + + void pourInCup() + { + writeln("Pouring into cup"); + } +} diff --git a/templatemethod/sort/app.d b/templatemethod/sort/app.d new file mode 100644 index 0000000..5fc5168 --- /dev/null +++ b/templatemethod/sort/app.d @@ -0,0 +1,31 @@ +import std.stdio : writeln; +import std.algorithm : sort; +import duck; + +void main() +{ + Duck[] ducks = [ + new Duck("Daffy", 8), + new Duck("Dewey", 2), + new Duck("Howard", 7), + new Duck("Louie", 2), + new Duck("Donald", 10), + new Duck("Huey", 2) + ]; + + writeln("Before sorting:"); + display(ducks); + + ducks.sort(); + + writeln("\nAfter sorting:"); + display(ducks); +} + +void display(Duck[] ducks) +{ + foreach (val; ducks) + { + writeln(val); + } +} diff --git a/templatemethod/sort/duck.d b/templatemethod/sort/duck.d new file mode 100644 index 0000000..ed9c35e --- /dev/null +++ b/templatemethod/sort/duck.d @@ -0,0 +1,37 @@ +module duck; + +import std.conv : to; +import std.stdio : writeln; + +class Duck +{ + private string name; + private int weight; + + this(string name, int weight) + { + this.name = name; + this.weight = weight; + } + + override string toString() const @safe pure nothrow + { + return name ~ " weighs " ~ weight.to!string; + } + + int opCmp(const Duck otherDuck) const @safe pure nothrow + { + if (weight < otherDuck.weight) + { + return -1; + } + else if (weight == otherDuck.weight) + { + return 0; + } + else + { + return 1; + } + } +}