Skip to content
Advertisement

How to implement a factory class?

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
User contributions licensed under: CC BY-SA
2 People found this is helpful
Advertisement