Factory in Python
What is that crap

Define an interface for creating an object,
but let the subclasses decide which class to
instantiate.

The Factory method lets a class defer
instantiation to subclasses.
A Simple Diagram
Different Factory Types

    x   •Static
    x   •Polymorphic
    x   •Abstract
Static Factory
• Forces all the creation operations to be
  focused in one spot
                                  Static Factory:
                                      Shape
      Circle




      Square                         Product
class Shape(object):
   def factory(type):
     if type == "Circle" : return Circle()
     if type == "Square" : return Square()
     assert 1, "Bad shape creation " + type
   factory = staticmethod(factory)

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"

def shape_name_gen(n):
  types = Shape.__subclasses__()
  for i in range(n):
     yield random.choice(types).__name__
shapes = [Shape.factory(i) for i in shape_name_gen(7)]

for shape in shapes:
shape.draw()
shape.erase()
Polymorphic Factory
• Make a single superclass version of the method that calls a
  Factory Method to handle the instantiation
• The new class can be dynamically added to the factory
• Factory methods are in separate class as virtual function
• Different types of factories can be subclassed from the basic
  factory
class ShapeFactory:
   factories = {}
   def add_factory(id, shapefactory):
ShapeFactory.factories.put[id] = shapeFactory
add_factory = staticmethod(add_factory)

def create_shape(id):
     if not ShapeFactory.factories.has_key(id):
ShapeFactory.factories[id] = eval(id+'.Factory()')
     return ShapeFactory.factories[id].create()
create_shape = staticmethod(create_shape)

class Shape(object): pass

class Circle(Shape):                            def shape_name_gen(n):
   def draw(self): print "Circle.draw"            types = Shape.__subclasses__()
   def erase(self): print "Circle.erase"          for i in range(n):
class Factory:                                       yield random.choice(types).__name__
     def create(self): return Circle()
                                                shapes = [ShapeFactory.create_shape(i) 
class Square(Shape):                                for i in shape_name_gen(7)]
   def draw(self): print "Square.draw"
   def erase(self): print "Square.erase"        for shape in shapes:
   class Factory:                               shape.draw()
      def create(self): return Square()         shape.erase()
Abstract Factory
• The client creates a concrete
  implementation of the
  abstract factory and then
  uses the generic interface to
  create object
• The idea is that at the point
  of creation of the factory
  object, you decide how all the
  objects created by that
  factory will be used.
class Obstacle: pass                    class GameElementFactory: pass
class Player: pass
                                        class JavAndPuzzle(GameElementFactory):
class Jav(Player):                         def make_player(self): return Jav()
   def interact_with(self, obstacle):      def make_obstacle(self): return Puzzle()
print("Jav is playing a" )
obstacle.action()                       class
                                        BenAndWeapon(GameElementFactory):
class Ben(Player):                         def make_player(self): return Ben()
   def interact_with(self, obstacle):      def make_obstacle(self): return Weapon()
print("Ben is playing a " )             class GameEnvironment:
obstacle.action()                          def __init__(self, factory):
                                        self.factory = factory
class Puzzle(Obstacle):                 self.p = factory.make_player()
   def action(self):                    self.ob = factory.make_obstacle()
print("Puzzle")
                                          def play(self):
class Weapon(Obstacle):                 self.p.interact_with(self.ob)
   def action(self):
print("Weapon")                         g1 = GameEnvironment(JavAndPuzzle())
                                        g2 = GameEnvironment(BenAndWeapon())
                                        g1.play()
                                        g2.play()
Limitations of Factory
• The first limitation is that refactoring an
  existing class to use factories breaks existing
  clients.

Factory in python

  • 1.
  • 2.
    What is thatcrap Define an interface for creating an object, but let the subclasses decide which class to instantiate. The Factory method lets a class defer instantiation to subclasses.
  • 3.
  • 4.
    Different Factory Types x •Static x •Polymorphic x •Abstract
  • 5.
    Static Factory • Forcesall the creation operations to be focused in one spot Static Factory: Shape Circle Square Product
  • 6.
    class Shape(object): def factory(type): if type == "Circle" : return Circle() if type == "Square" : return Square() assert 1, "Bad shape creation " + type factory = staticmethod(factory) 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" def shape_name_gen(n): types = Shape.__subclasses__() for i in range(n): yield random.choice(types).__name__ shapes = [Shape.factory(i) for i in shape_name_gen(7)] for shape in shapes: shape.draw() shape.erase()
  • 7.
    Polymorphic Factory • Makea single superclass version of the method that calls a Factory Method to handle the instantiation • The new class can be dynamically added to the factory • Factory methods are in separate class as virtual function • Different types of factories can be subclassed from the basic factory
  • 8.
    class ShapeFactory: factories = {} def add_factory(id, shapefactory): ShapeFactory.factories.put[id] = shapeFactory add_factory = staticmethod(add_factory) def create_shape(id): if not ShapeFactory.factories.has_key(id): ShapeFactory.factories[id] = eval(id+'.Factory()') return ShapeFactory.factories[id].create() create_shape = staticmethod(create_shape) class Shape(object): pass class Circle(Shape): def shape_name_gen(n): def draw(self): print "Circle.draw" types = Shape.__subclasses__() def erase(self): print "Circle.erase" for i in range(n): class Factory: yield random.choice(types).__name__ def create(self): return Circle() shapes = [ShapeFactory.create_shape(i) class Square(Shape): for i in shape_name_gen(7)] def draw(self): print "Square.draw" def erase(self): print "Square.erase" for shape in shapes: class Factory: shape.draw() def create(self): return Square() shape.erase()
  • 9.
    Abstract Factory • Theclient creates a concrete implementation of the abstract factory and then uses the generic interface to create object • The idea is that at the point of creation of the factory object, you decide how all the objects created by that factory will be used.
  • 10.
    class Obstacle: pass class GameElementFactory: pass class Player: pass class JavAndPuzzle(GameElementFactory): class Jav(Player): def make_player(self): return Jav() def interact_with(self, obstacle): def make_obstacle(self): return Puzzle() print("Jav is playing a" ) obstacle.action() class BenAndWeapon(GameElementFactory): class Ben(Player): def make_player(self): return Ben() def interact_with(self, obstacle): def make_obstacle(self): return Weapon() print("Ben is playing a " ) class GameEnvironment: obstacle.action() def __init__(self, factory): self.factory = factory class Puzzle(Obstacle): self.p = factory.make_player() def action(self): self.ob = factory.make_obstacle() print("Puzzle") def play(self): class Weapon(Obstacle): self.p.interact_with(self.ob) def action(self): print("Weapon") g1 = GameEnvironment(JavAndPuzzle()) g2 = GameEnvironment(BenAndWeapon()) g1.play() g2.play()
  • 11.
    Limitations of Factory •The first limitation is that refactoring an existing class to use factories breaks existing clients.