-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Darko Draskovic <[email protected]>
- Loading branch information
1 parent
f20c8fa
commit 4183ef4
Showing
3 changed files
with
197 additions
and
3 deletions.
There are no files selected for viewing
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
from abc import ABC | ||
from enum import Enum, auto | ||
|
||
|
||
# object hierarchy | ||
|
||
# abstract object | ||
class HotDrink(ABC): | ||
quantity: int | ||
|
||
def consume(self) -> None: | ||
pass | ||
|
||
|
||
class Tea(HotDrink): | ||
def consume(self) -> None: | ||
print(f"You consume {self.quantity}ml of tea!") | ||
|
||
|
||
class Coffee(HotDrink): | ||
def consume(self) -> None: | ||
print(f"You consume {self.quantity}ml of coffee!") | ||
|
||
|
||
# factory hierarchy | ||
|
||
# abstract factory; used to mandate interface | ||
# essential in strongly typed languages, optional in Python | ||
class HotDrinkFactory(ABC): | ||
def prepare(self, quantity: int) -> HotDrink: | ||
pass | ||
|
||
|
||
class TeaFactory(ABC): | ||
def prepare(self, quantity: int) -> HotDrink: | ||
tea = Tea() | ||
tea.quantity = quantity | ||
return tea | ||
|
||
|
||
class CoffeeFactory(ABC): | ||
def prepare(self, quantity: int) -> HotDrink: | ||
coffee = Coffee() | ||
coffee.quantity = quantity | ||
return coffee | ||
|
||
|
||
def make_drink(type: str) -> HotDrink | None: | ||
if type == "tea": | ||
return TeaFactory().prepare(200) | ||
elif type == "coffee": | ||
return CoffeeFactory().prepare(50) | ||
else: | ||
return None | ||
|
||
|
||
class HotDrinkMachine: | ||
factories: list[tuple[str, HotDrinkFactory]] = [] | ||
_initialized: bool = False | ||
|
||
class AvailableDrink(Enum): | ||
TEA = auto() | ||
COFFEE = auto() | ||
|
||
def __init__(self) -> None: | ||
if not self._initialized: | ||
for d in self.AvailableDrink: | ||
name = d.name[0] + d.name[1:].lower() | ||
factory_name = name + "Factory" | ||
factory_instance = eval(factory_name)() | ||
self.factories.append((name, factory_instance)) | ||
self._initialized = True | ||
pass | ||
|
||
def make_drink(self) -> HotDrink: | ||
print("Available drinks: ") | ||
for i in range(len(self.factories)): | ||
print(str(i) + f": {self.factories[i][0]}") | ||
|
||
s = input(f"Pick a drink (0-{len(self.factories)-1}): ") | ||
idx = int(s) | ||
s = input("Specify quantity: ") | ||
quantity = int(s) | ||
return self.factories[idx][1].prepare(quantity) | ||
|
||
|
||
if __name__ == "__main__": | ||
# entry = input("Please choose a drink: ") | ||
# drink = make_drink(entry) | ||
# if drink: | ||
# drink.consume() | ||
|
||
hdm = HotDrinkMachine() | ||
drink = hdm.make_drink() | ||
drink.consume() |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
from math import sin, cos, pi | ||
from enum import Enum | ||
|
||
|
||
class CoordinateSystem(Enum): | ||
CARTESIAN = 1 | ||
POLAR = 2 | ||
|
||
|
||
# class that does not use factory method | ||
class Point_0: | ||
x: float | ||
y: float | ||
|
||
def __init__( | ||
self, a: float, b: float, system: CoordinateSystem = CoordinateSystem.CARTESIAN | ||
) -> None: | ||
if system == CoordinateSystem.CARTESIAN: | ||
self.x = a | ||
self.y = b | ||
elif system == CoordinateSystem.POLAR: | ||
self.x = a * cos(b) | ||
self.y = a * sin(b) | ||
|
||
|
||
# class that uses factory method | ||
class Point: | ||
x: float | ||
y: float | ||
|
||
def __init__(self, x: float = 0, y: float = 0) -> None: | ||
self.x = x | ||
self.y = y | ||
|
||
def __str__(self) -> str: | ||
return f"x: {self.x}, y: {self.y}" | ||
|
||
# factory is a method that creates an object; it is an aleternative to constructors and | ||
# initalizers with multiple, special case parameters | ||
@staticmethod | ||
def new_cartesian(x: float, y: float) -> "Point": | ||
return Point(x, y) | ||
|
||
@staticmethod | ||
def new_polar(rho: float, theta: float) -> "Point": | ||
return Point(rho * cos(theta), rho * sin(theta)) | ||
|
||
# factory can be an inner class (no point doing this in Python, though, becasause | ||
# everything is public) | ||
class PointFactory: | ||
def new_cartesian(self, x: float, y: float) -> "Point": | ||
# use no params constructor to semantically decouple class factory from object class | ||
p: Point = Point() | ||
p.x = x | ||
p.y = y | ||
return p | ||
|
||
def new_polar(self, rho: float, theta: float) -> "Point": | ||
return Point(rho * cos(theta), rho * sin(theta)) | ||
|
||
# singleton factory instance | ||
factory = PointFactory() | ||
|
||
|
||
# Alternative is to create a factory with factory methods | ||
# factory class is coupled to an object class/definition | ||
class PointFactory: | ||
@staticmethod | ||
def new_cartesian(x: float, y: float) -> "Point": | ||
# use no params constructor to semantically decouple class factory from object class | ||
p: Point = Point() | ||
p.x = x | ||
p.y = y | ||
return p | ||
|
||
@staticmethod | ||
def new_polar(rho: float, theta: float) -> "Point": | ||
return Point(rho * cos(theta), rho * sin(theta)) | ||
|
||
|
||
if __name__ == "__main__": | ||
# use constructor | ||
p1 = Point(10, 15) | ||
|
||
# use factory methods | ||
p2 = Point.new_cartesian(12, 24.5) | ||
|
||
p3 = Point.new_polar(1, pi / 4) | ||
|
||
p4 = Point.factory.new_cartesian(1, 1) | ||
print(p4) | ||
|
||
print() |