Using enums in Python
The posted code doesn't take advantage of most of the benefits provides by enums in Python.
The typical use case of enums is to make decisions depending on a given enum member. For example, in the context of the posted code, I can imagine a create_foo
method which takes as parameter a value of Color
type that is an enum, and callers would use create_foo(Color.RED)
to create a foo object with one of the supported colors.
Another common use case would be iterating over an enum type, for example to display the available choices to users.
In the posted code, only the iteration capability is used, and only internally. For this simpler purpose, a simpler and better option would be using a dictionary:
SUPPORTED_COLORS = { "red": Red, "blue": Blue, } def create_color(name): if name in SUPPORTED_COLORS: return SUPPORTED_COLORS[name]() return Blue()
Since the parameter of the factory method is a string, it doesn't help to find the accepted values. I have to read the implementation to know, which violates good encapsulation.
You may argue that taking a string parameter makes it possible to accept unsupported values and fall back to a default. I think that without a specific use case to justify this need, it's likely to be more harmful than beneficial to bypass type safety this way.
I find it unexpected to have a factory method as part of an enum type. I would not look for a factory method there. When I see an enum, I expect to use its members, or iterate over it.
Based on the documentation of enum support, enum members should be named with UPPER_CASE
, for example:
class Color(Enum): RED = auto BLUE = auto
Based on the examples on the page, it seems that singular noun is recommended as the name of the enum (Color
rather than Colors
).
Implementing the factory method pattern in Python
I wanted to have a factory-method, but without the if statements that are often seen in examples of this pattern.
Why is that, really? What is the real problem you're trying to solve? When you try to do something that is different from what is "often seen", I suggest to take a step back, and ask yourself if you really have a good reason to not follow a well established pattern. Chances are that you are missing something, or you don't have a real need.
Also keep in mind that "often seen" patterns are easier for everyone to understand, because they are often seen. When you take a different approach, there is a high risk that readers will be surprised by it. So it had better have a good justification to exist, and be rock solid.
There is nothing fundamentally wrong with if statements in the factory method in general. On the other hand, I can imagine situations where a complex if-else chain could be replaced with something better, but I would have to be more specific about the problem to justify the need for improvement.
I was surprised by the posted code, at multiple points. When I read the question title "Factory pattern using enum", I expected to see:
- A factory method that takes an enum parameter
- The factory method decides what to return based on the enum parameter
Reading on, when I saw "but without the if
statements", I expected a dictionary mapping enum members to some value or creator function, replacing if-else chain with dictionary lookup.
I think this tutorial on realpython.com explains very nicely how to implement this pattern well in Python.