diff --git a/abstract_factory.dart b/abstract_factory.dart new file mode 100644 index 0000000..1131692 --- /dev/null +++ b/abstract_factory.dart @@ -0,0 +1,55 @@ +abstract class Drinkable { + void pour(); +} + +class Beer implements Drinkable { + void pour() { + print("Pouring a delicious beer!"); + } +} + +class Coffee implements Drinkable { + void pour() { + print("Pouring a refreshing coffee!"); + } +} + +abstract class DrinkFactory { + Drinkable createDrink(); + DrinkFactory(); +} + +class Pub implements DrinkFactory { + Drinkable createDrink() { + return Beer(); + } +} + +class CoffeeShop implements DrinkFactory { + Drinkable createDrink() { + return Coffee(); + } +} + +void main() { + var mood = "sleepy"; + late DrinkFactory destination; + + switch (mood) { + case "sleepy": + destination = CoffeeShop(); + break; + case "done": + destination = Pub(); + break; + default: + print("I only have two moods..."); + } + + var myBeverage = destination.createDrink(); + myBeverage.pour(); + + /* + Pouring a refreshing coffee! + */ +} diff --git a/adapter.dart b/adapter.dart new file mode 100644 index 0000000..3c5cb01 --- /dev/null +++ b/adapter.dart @@ -0,0 +1,29 @@ +const adapteeMessage = 'Adaptee#method was called'; + +class Adaptee { + String method() { + print('Adaptee#method is being called'); + + return adapteeMessage; + } +} + +abstract class Target { + String call(); +} + +class Adapter implements Target { + String call() { + var adaptee = Adaptee(); + print('Adapter#call is being called'); + + return adaptee.method(); + } +} + +void main() { + var adapter = Adapter(); + var result = adapter.call(); + + assert(result == adapteeMessage); +} diff --git a/builder.dart b/builder.dart new file mode 100644 index 0000000..2b90ea4 --- /dev/null +++ b/builder.dart @@ -0,0 +1,85 @@ +class PizzaBuilder { + late String _crust; + int _diameter; + late Set _toppings; + + PizzaBuilder(this._diameter); + + String get crust => _crust; + set crust(String newCrust) { + _crust = newCrust; + } + + int get diameter => _diameter; + set diameter(int newDiameter) { + _diameter = newDiameter; + } + + Set get toppings => _toppings; + set toppings(Set newToppings) { + _toppings = newToppings; + _ensureCheese(); + } + + void _ensureCheese() { + _toppings.add("cheese"); + } + + Pizza build() { + return Pizza(this); + } +} + +class Pizza { + late String _crust; + late int _diameter; + late Set _toppings; + + Pizza(PizzaBuilder builder) { + _crust = builder.crust; + _diameter = builder.diameter; + _toppings = builder.toppings; + } + + String get crust => _crust; + int get diameter => _diameter; + String get toppings => _stringifiedToppings(); + String _stringifiedToppings() { + var stringToppings = _toppings.join(", "); + var lastComma = stringToppings.lastIndexOf(","); + var replacement = ",".allMatches(stringToppings).length > 1 ? ", and" : " and"; + + return stringToppings.replaceRange(lastComma, lastComma + 1, replacement); + } + + @override + String toString() { + return "A delicous $_diameter\" pizza with $_crust crust covered in $toppings"; + } +} + +void main() { + // Create a handy PizzaBuilder with an 8" diameter. + var pizzaBuilder = PizzaBuilder(8); + + // Add some attributes to the builder. + pizzaBuilder.crust = "deep dish"; + pizzaBuilder.toppings = Set.from(["pepperoni"]); + + // Let's make a pizza! + var plainPizza = Pizza(pizzaBuilder); + print("Behold! $plainPizza."); + assert(plainPizza.toString() == "Behold! A delicous 8\" pizza with deep dish crust covered in pepperoni and cheese."); + + // Now to adjust some things for the next pizza... + pizzaBuilder.crust = "gold plated"; + pizzaBuilder.diameter = 72; + pizzaBuilder.toppings = Set.from(["anchovies", "caviar", "diamonds"]); + + // The beauty of the build is you can quickly iterate and produce instances of a class. + // For example, we have an early employee of the latest unicorn in line. So much disposable income! + // Also note, we use the .build() function of the builder this time. + var luxuriousPizza = pizzaBuilder.build(); + print("Wow! $luxuriousPizza? Someone is rich!"); + assert(luxuriousPizza.toString() == "Wow! A delicous 72\" pizza with gold plated crust covered in anchovies, caviar, diamonds, and cheese? Someone is rich!"); +} diff --git a/decorator.dart b/decorator.dart new file mode 100644 index 0000000..01616eb --- /dev/null +++ b/decorator.dart @@ -0,0 +1,49 @@ +abstract class Beverage { + double get cost; + String get ingredients; +} + +class Ingredient { + double cost; + String name; + + Ingredient(this.name, this.cost); + + @override + String toString() => this.name; +} + +var coffee = Ingredient("coffee", .25); +var milk = Ingredient("milk", .5); +var sugar = Ingredient("sugar", .1); + +class Coffee implements Beverage { + Set _ingredients = Set.from([coffee, milk, sugar]); + double get cost => _ingredients.fold(0, (total, i) => total + i.cost); + String get ingredients { + var stringIngredients = _ingredients.fold("", (String str, i) => str + "${i.name}, "); + var trimmedString = stringIngredients.substring(0, stringIngredients.length - 2); + var lastComma = trimmedString.lastIndexOf(","); + var replacement = ",".allMatches(trimmedString).length > 1 ? ", and" : " and"; + + return trimmedString.replaceRange(lastComma, lastComma + 1, replacement); + } +} + +class StarbucksCoffeeDecorator implements Beverage { + Beverage _coffee = Coffee(); + double get cost => _coffee.cost * 5; + String get ingredients => _coffee.ingredients; +} + +void main() { + var coffee = Coffee(); + var starbucksCoffee = StarbucksCoffeeDecorator(); + + print("Coffee contains ${coffee.ingredients}. It costs \$${coffee.cost}"); + print("Starbucks coffee contains ${starbucksCoffee.ingredients}. It costs \$${starbucksCoffee.cost}"); + + // Coffee contains coffee, milk, and sugar. It costs $0.85 + // Starbucks coffee contains coffee, milk, and sugar. It costs $4.25 +} + diff --git a/facade.dart b/facade.dart new file mode 100644 index 0000000..6f0fc10 --- /dev/null +++ b/facade.dart @@ -0,0 +1,74 @@ +class Grinder { + String _type; + + Grinder(this._type); + + void grind() { + print("Grinding $_type!"); + } +} + +class Maker { + String _type; + + Maker(this._type); + + void fill() { + print("Filling the $_type maker!"); + } + + void retrieve() { + print("Retrieving the $_type!"); + } + + void start() { + print("Starting the $_type maker!"); + } +} + +class Imbiber { + String _beverage; + + Imbiber(this._beverage); + + void drink() { + print("Mmmmm...drinking $_beverage!"); + } +} + +class MorningFacade { + final _coffeeDrinker = Imbiber("coffee"); + final _coffeeGrinder = Grinder("coffee beans"); + final _coffeeMaker = Maker("coffee"); + + void prepareCoffee() { + print("\r\nPreparing the coffee..."); + _coffeeGrinder.grind(); + _coffeeMaker + ..fill() + ..start(); + print("Coffee is brewing!\r\n"); + } + + void drinkCoffee() { + print("\r\nMust...have...coffee..."); + _coffeeMaker.retrieve(); + _coffeeDrinker.drink(); + print("This is damn fine coffee!"); + } +} + +void main() { + var typicalMorning = MorningFacade(); + + print("Wake up! Grab a brush and put on a little makeup..."); + print("\r\nStumble to the kitchen..."); + + typicalMorning.prepareCoffee(); + + print("Oh my...that smells good..."); + + typicalMorning.drinkCoffee(); + + print("\r\nI'm ready to attack the day!"); +} diff --git a/flyweight.dart b/flyweight.dart new file mode 100644 index 0000000..b71f6ab --- /dev/null +++ b/flyweight.dart @@ -0,0 +1,105 @@ +import "dart:collection"; + +class Letter { + late String letter; + Letter(String l) { + if (l.length != 1) { throw new Exception("Can only be a single letter"); } + letter = l; + } + + @override + String toString() => letter; +} + +class Sentence { + List letters = []; + void addLetter(Letter letter) => letters.add(letter); + + @override + String toString() => letters.join(""); +} + +class LetterFactory { + Map letters = {}; + + Letter fetchLetter(String l) { + if (letters.containsKey(l)) { return letters[l]!; } + var letter = Letter(l); + letters[l] = letter; + return letter; + } + + int get lettersCreated => letters.length; +} + +class Document { + LetterFactory letterFactory = LetterFactory(); + int lettersWritten = 0; + late SplayTreeMap sentences; + + Document() { + sentences = new SplayTreeMap(); + } + + void export() => sentences.forEach((k, v) => print("$v")); + + void write(int sentenceKey, String letterString) { + if (!sentences.containsKey(sentenceKey)) { + sentences[sentenceKey] = Sentence(); + } + + var l = letterFactory.fetchLetter(letterString); + sentences[sentenceKey]!.addLetter(l); + lettersWritten++; + } + + int get lettersCreated => letterFactory.lettersCreated; +} + +void main() { + var doc = Document(); + + doc.write(6, "t"); + doc.write(7, "u"); + doc.write(1, "A"); + doc.write(2, "y"); + doc.write(7, "s"); + doc.write(3, "b"); + doc.write(2, "o"); + doc.write(3, "a"); + doc.write(2, "u"); + doc.write(1, "l"); + doc.write(3, "s"); + doc.write(3, "e"); + doc.write(4, "a"); + doc.write(1, "l"); + doc.write(2, "r"); + doc.write(5, "b"); + doc.write(5, "e"); + doc.write(5, "l"); + doc.write(5, "o"); + doc.write(4, "r"); + doc.write(5, "n"); + doc.write(4, "e"); + doc.write(6, "o"); + doc.write(5, "g"); + + doc.export(); + + print("\r\nDocument wrote: ${doc.lettersWritten}."); + print("Letters created: ${doc.lettersCreated}."); + + /* + All + your + base + are + belong + to + us + + Document wrote: 24. + Letters created: 13. + */ +} + diff --git a/singleton.dart b/singleton.dart new file mode 100644 index 0000000..01dc8d0 --- /dev/null +++ b/singleton.dart @@ -0,0 +1,34 @@ +class Me { + static final Me _singleton = new Me._internal(); + static final String _name = "Tyler"; + + factory Me() { + return _singleton; + } + + static String get name => _name; + + @override + String toString() => "Hello, my name is $name."; + + Me._internal(); +} + +void main() { + var tyler = Me(); + var anotherTyler = Me(); + + print(tyler); + print(anotherTyler); + + var samenessCheck = identical(tyler, anotherTyler) + ? "We are both the same ${Me.name}." + : "We are NOT the same. I mean, just look at us."; + print(samenessCheck); + + /* + Hello, my name is Tyler. + Hello, my name is Tyler. + We are both the same Tyler. + */ +} diff --git a/strategy.dart b/strategy.dart new file mode 100644 index 0000000..a7a1ca2 --- /dev/null +++ b/strategy.dart @@ -0,0 +1,50 @@ +abstract class CoffeeStrategy { + String announce(String roast); +} + +class AmericanoStrategy implements CoffeeStrategy { + String announce(String roast) => "an Americano with $roast beans"; +} + +class DripStrategy implements CoffeeStrategy { + String announce(String roast) => "a drip coffee with $roast beans"; +} + +class MochaFrappuccinoStrategy implements CoffeeStrategy { + String announce(String roast) => "a delicious mocha frappuccion with $roast beans"; +} + +class CoffeeDrinker { + CoffeeStrategy preferredDrink; + String name; + CoffeeDrinker(this.name, this.preferredDrink); +} + +void main() { + var americano = AmericanoStrategy(); + var drip = DripStrategy(); + var mocha = MochaFrappuccinoStrategy(); + + var me = CoffeeDrinker("Tyler", drip); + var europeanBuddy = CoffeeDrinker("Pieter", americano); + var myDaughter = CoffeeDrinker("Joanie", mocha); + + final String roastOfTheDay = "Italian"; + + for (var person in [me, europeanBuddy, myDaughter]) { + print("Hey ${person.name}, whatcha drinkin' over there?"); + print("I'm enjoying ${person.preferredDrink.announce(roastOfTheDay)}!\r\n"); + } + + /* + Hey Tyler, whatcha drinkin' over there? + I'm enjoying a drip coffee with Italian beans! + + Hey Pieter, whatcha drinkin' over there? + I'm enjoying an Americano with Italian beans! + + Hey Joanie, whatcha drinkin' over there? + I'm enjoying a delicious mocha frappuccion with Italian beans! + */ +} +