Vending Machine Method (Factory Method) is a creational design pattern:
š¤š¤š¤š¤š¤
Abstract Vending Machine(Abstract Factory) is a creational design pattern:
š¤š¤š¤š¤š¤
What is Vending Machine(Simple Factory)?
It’s a way to create:
- a class
Vending Machine
creating objects without requiring any concrete classes RegularBeverage,DietBeverage
.
Vending Machine
looks handsome and famous, but it’s not a member of the GoF family. I’ve talked about it before.
What is Vending Machine Method(Factory Method)?
It’s a way to create:
- a Parent(Super) class
Vending Machine
- with an abstractmethod
def create_beverage: return None
to generate the specific product.
- with a common method
def show_info
to return the product’s info
- Sub(Child/Inherited) classes
RegularVendingMachine, DietVendingMachine
will redefine what product RegularBeverage(),DietBeverage()
will be returned.
What is Abstract Vending Machine(Abstract Factory)?
same as Machine Method(Factory Method), but it can generate many beverage, snack
kind of products instead of only one beverage
It’s a way to create:
- a Parent(Super) class
Vending Machine
defines abstractmethod(s) def create_beverage: return None, def create_snack: return None
to generate the product.
- Sub(Child/Inherited) classes
RegularVendingMachine, DietVendingMachine
will redefine what productRegularBeverage,DietBeverage,RegularSnack,DietSnack
will be returned.
Why use Vending Machine?
It makes generating the products RegularBeverage, DietBeverage
easier!
Why use Vending Machine Method?
Question: Can you edit the product classesBeverage,RegularBeverage,DietBeverage
(is it yours)?
Answer: Yes
- Just using Vending Machine is enough! It may require editing the product classes a bit, but it’s nicer. Don’t use Vending Machine Method if you don’t really need it.
Answer: No
- Okay, Vending Machine Method is helpful when you can’t edit the product classes (it’s not your classes, can’t touch it).
- Vending Machine Method lets a class defer (postpone, delay) instantiation to subclasses.
- Your subclasses
RegularVendingMachine,DietVendingMachine,...
will:
- inherit your superclass
VendingMachine
- redefines the generation method
def create_beverage
in its own way
- then subclasses generate products
RegularBeverage, DietBeverage, ...
that have common methodsdef show_info
, properties of superclass without redefinition.
Why use Abstract Vending Machine?
When you want to use Vending Machine Method, but you can not!
Because have more Beverage, Snack
than one Beverage(Regular,Diet)
kind of product need to be handled
When products are:
Beverage, Snack
can use Vending Machine Method
RegularBeverage, DietBeverage
can use Vending Machine Method
RegularSnack, DietSnack
can use Vending Machine Method
When products are:
RegularBeverage, DietBeverage, RegularSnack, DietSnack
can use Abstract Vending Machine
When to use Vending Machine?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
from abc import ABC, abstractmethod
class Beverage(ABC):
@abstractmethod
def make_burp(self):
pass
# Q:Can you edit the product classes? A:Yes.
# Since this class can be edited, we add `def show_info` here for later use
def show_info(self):
info = {
**self.__dict__,
"type": type(self),
"burp_sound": self.make_burp(),
}
return info
class RegularBeverage(Beverage):
def make_burp(self):
return "BURP"
class DietBeverage(Beverage):
def make_burp(self):
return "Diet - BURP"
|
Expected Output:
1
2
|
{'type': <class 'RegularBeverage'>, 'burp_sound': 'BURP'}
{'type': <class 'DietBeverage'>, 'burp_sound': 'Diet - BURP'}
|
When to use Vending Machine Method?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
from abc import ABC, abstractmethod
class Beverage(ABC):
@abstractmethod
def make_burp(self):
pass
# Q:Can you edit the product classes? A:No.
# Since this class is immutable, we can not add `def show_info` here, we have to find another way like, wrap from the outside!
class RegularBeverage(Beverage):
def make_burp(self):
return "BURP"
class DietBeverage(Beverage):
def make_burp(self):
return "Diet - BURP"
|
Expected Output:
1
2
|
{'type': <class 'RegularBeverage'>, 'burp_sound': 'BURP'}
{'type': <class 'DietBeverage'>, 'burp_sound': 'Diet - BURP'}
|
When to use Abstract Vending Machine?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
from abc import ABC, abstractmethod
class Beverage(ABC):
@abstractmethod
def make_burp(self):
pass
class Snack(ABC):
@abstractmethod
def make_thirsty(self):
pass
class RegularBeverage(Beverage):
def make_burp(self):
return "BURP"
class RegularSnack(Snack):
def make_thirsty(self):
return "I'm thirsty"
class DietBeverage(Beverage):
def make_burp(self):
return "Diet - BURP"
class DietSnack(Snack):
def make_thirsty(self):
return "Diet - I'm thirsty"
|
Expected Output:
1
2
3
4
5
6
7
8
|
{'type': <class 'RegularBeverage'>, 'burp_sound': 'BURP'}
- "BURP"
{'type': <class 'RegularSnack'>, 'thirsty_sound': "I'm thirsty"}
- "I'm thirsty"
{'type': <class 'DietBeverage'>, 'burp_sound': 'Diet - BURP'}
- "Diet - BURP"
{'type': <class 'DietSnack'>, 'thirsty_sound': "Diet - I'm thirsty"}
- "Diet - I'm thirsty"
|
How to implement Vending Machine?
1
2
3
4
5
6
7
8
9
10
11
12
|
class BeverageVendingMachine:
def generate(self, beverage_type):
if beverage_type == "Regular":
return RegularBeverage()
elif beverage_type == "Diet":
return DietBeverage()
if __name__ == "__main__":
for beverage_type in ("Regular", "Diet"):
beverage = BeverageVendingMachine().generate(beverage_type)
print(beverage.show_info())
|
Source Code: Vending Machine
How to implement Vending Machine Method?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
class VendingMachine(ABC):
@abstractmethod
def create_beverage(self):
pass
def show_info(self):
beverage = self.create_beverage()
info = {
**beverage.__dict__,
"type": type(beverage),
"burp_sound": beverage.make_burp(),
}
return info
class RegularVendingMachine(VendingMachine):
def create_beverage(self):
return RegularBeverage()
class DietVendingMachine(VendingMachine):
def create_beverage(self):
return DietBeverage()
if __name__ == "__main__":
for vending_machine in (RegularVendingMachine(), DietVendingMachine()):
print(vending_machine.show_info())
|
Source Code: Vending Machine Method
How to implement Abstract Vending Machine?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
|
class AbstractVendingMachine(ABC):
@abstractmethod
def create_beverage(self):
pass
@abstractmethod
def create_snack(self):
pass
def show_beverage_info(self):
beverage = self.create_beverage()
info = {
**beverage.__dict__,
"type": type(beverage),
"burp_sound": beverage.make_burp(),
}
return info
def show_snack_info(self):
snack = self.create_snack()
info = {
**snack.__dict__,
"type": type(snack),
"thirsty_sound": snack.make_thirsty(),
}
return info
class RegularVendingMachine(AbstractVendingMachine):
def create_beverage(self):
return RegularBeverage()
def create_snack(self):
return RegularSnack()
class DietVendingMachine(AbstractVendingMachine):
def create_beverage(self):
return DietBeverage()
def create_snack(self):
return DietSnack()
if __name__ == "__main__":
for vending_machine in (RegularVendingMachine(), DietVendingMachine()):
beverage_vending_machine = vending_machine.create_beverage()
print(vending_machine.show_beverage_info())
print(f' - "{beverage_vending_machine.make_burp()}"')
snack_vending_machine = vending_machine.create_snack()
print(vending_machine.show_snack_info())
print(f' - "{snack_vending_machine.make_thirsty()}"')
|
Source Code: Abstract Vending Machine