I want to be able to create objects based on an enumeration class, and use a dictionary. Something like this:
class IngredientType(Enum): SPAM = auto() # Some spam BAKE_BEANS = auto() # Baked beans EGG = auto() # Fried egg class Ingredient(object): pass class Spam(Ingredient): pass class BakedBeans(Ingredient): pass class Egg(Ingredient): pass class IngredientFactory(object): """Factory makes ingredients""" choice = { IngredientType.SPAM: IngredientFactory.MakeSpam, IngredientType.BAKED_BEANS: IngredientFactory.MakeBakedBeans, IngredientType.EGG: IngredientFactory.MakeEgg } @staticmethod def make(type): method = choice[type] return method() @staticmethod def makeSpam(): return Spam() @staticmethod def makeBakedBeans(): return BakedBeans() @staticmethod def makeEgg(): return Egg()
But I get the error:
NameError: name 'IngredientFactory' is not defined
For some reason the dictionary can’t be created. Where am I going wrong here?
Advertisement
Answer
After looking at Bruce Eckel’s book I came up with this:
#Based on Bruce Eckel's book Python 3 example # A simple static factory method. from __future__ import generators import random from enum import Enum, auto class ShapeType(Enum): CIRCLE = auto() # Some circles SQUARE = auto() # some squares class Shape(object): pass class Circle(Shape): def draw(self): print("Circle.draw") def erase(self): print("Circle.erase") class Square(Shape): def draw(self): print("Square.draw") def erase(self): print("Square.erase") class ShapeFactory(object): @staticmethod def create(type): #return eval(type + "()") # simple alternative if type in ShapeFactory.choice: return ShapeFactory.choice[type]() assert 0, "Bad shape creation: " + type choice = { ShapeType.CIRCLE: Circle, ShapeType.SQUARE: Square } # Test factory # Generate shape name strings: def shapeNameGen(n): types = list(ShapeType) for i in range(n): yield random.choice(types) shapes = [ ShapeFactory.create(i) for i in shapeNameGen(7)] for shape in shapes: shape.draw() shape.erase()
This gets the user to select a class type from the enumeration, and blocks any other type. It also means user’s are less likely to write ‘bad strings’ with spelling mistakes. They just use the enums. The output from the test is then, something like this:
Circle.draw Circle.erase Circle.draw Circle.erase Square.draw Square.erase Square.draw Square.erase Circle.draw Circle.erase Circle.draw Circle.erase Square.draw Square.erase