Last active
March 23, 2018 06:03
-
-
Save carlosypunto/a179a9203b60c7b1c19357af717d0f54 to your computer and use it in GitHub Desktop.
Swift 2 Multiparadigm Decorator Pattern
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Decorable Protocol -------------------------------------------------------------------- | |
protocol IBeverage { | |
func description() -> String | |
func cost() -> Double | |
} | |
extension IBeverage { | |
func printDescription() { | |
print(self.description() + " $\(self.cost())" ) | |
} | |
} | |
// Decorator condiments Abstract Class --------------------------------------------------- | |
class Condiment: IBeverage { | |
let beverage: IBeverage | |
required init(beverage: IBeverage) { | |
self.beverage = beverage | |
} | |
func description() -> String { | |
fatalError("Not Implemented") | |
} | |
func cost() -> Double { | |
fatalError("Not Implemented") | |
} | |
} | |
// Functional IBeverage Protocol extension ----------------------------------------------- | |
extension IBeverage { | |
func decorateWithCondiments(condimentsTypes: [Condiment.Type]) -> IBeverage { | |
return condimentsTypes.reduce(self) { | |
return $1.init(beverage: $0) | |
} | |
} | |
} | |
// Concrete Decorable Beverage Classes --------------------------------------------------- | |
class HouseBlend: IBeverage { | |
func description() -> String { | |
return "House blended coffee" | |
} | |
func cost() -> Double { | |
return 0.89 | |
} | |
} | |
class DarkRoast: IBeverage { | |
func description() -> String { | |
return "Dark roast coffee" | |
} | |
func cost() -> Double { | |
return 0.99 | |
} | |
} | |
class Espresso: IBeverage { | |
func description() -> String { | |
return "Espressso coffee" | |
} | |
func cost() -> Double { | |
return 1.99 | |
} | |
} | |
// Concrete Decorador Condiments Classes ------------------------------------------------- | |
class Milk: Condiment { | |
override func description() -> String { | |
return self.beverage.description() + ", with Milk" | |
} | |
override func cost() -> Double { | |
return self.beverage.cost() + 0.10 | |
} | |
} | |
class Mocha: Condiment { | |
override func description() -> String { | |
return self.beverage.description() + ", with Mocha" | |
} | |
override func cost() -> Double { | |
return self.beverage.cost() + 0.20 | |
} | |
} | |
class Soy: Condiment { | |
override func description() -> String { | |
return self.beverage.description() + ", with Soy" | |
} | |
override func cost() -> Double { | |
return self.beverage.cost() + 0.15 | |
} | |
} | |
class Whip: Condiment { | |
override func description() -> String { | |
return self.beverage.description() + ", with Whip" | |
} | |
override func cost() -> Double { | |
return self.beverage.cost() + 1.00 | |
} | |
} | |
// Simulation ---------------------------------------------------------------------------- | |
// Without decoration | |
let beverage1 = Espresso() | |
beverage1.printDescription() | |
// Mutable variable (bad practice) | |
var beverage2: IBeverage = DarkRoast() | |
beverage2 = Mocha(beverage: beverage2) | |
beverage2 = Soy(beverage: beverage2) | |
beverage2 = Whip(beverage: beverage2) | |
beverage2.printDescription() | |
// functional complex way | |
let beverage3 = Whip(beverage: Mocha(beverage: Milk(beverage: DarkRoast()))) | |
beverage3.printDescription() | |
// functional easy way | |
let beverage4 = HouseBlend().decorateWithCondiments([Mocha.self, Milk.self, Whip.self]) | |
beverage4.printDescription() | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment