#: c11:FlowerVisitors.py
# Demonstration of "visitor" pattern.
from __future__ import generators
import random

# The Flower hierarchy cannot be changed:
class Flower(object):  
  def accept(self, visitor):
    visitor.visit(self)
  def pollinate(self, pollinator):
    print self, "pollinated by", pollinator
  def eat(self, eater):
    print self, "eaten by", eater
  def __str__(self): 
    return self.__class__.__name__

class Gladiolus(Flower): pass
class Runuculus(Flower): pass
class Chrysanthemum(Flower): pass 

class Visitor:
  def __str__(self): 
    return self.__class__.__name__

class Bug(Visitor): pass
class Pollinator(Bug): pass
class Predator(Bug): pass

# Add the ability to do "Bee" activities:
class Bee(Pollinator):
  def visit(self, flower):
      flower.pollinate(self)

# Add the ability to do "Fly" activities:
class Fly(Pollinator):
  def visit(self, flower):
      flower.pollinate(self)

# Add the ability to do "Worm" activities:
class Worm(Predator):
  def visit(self, flower):
      flower.eat(self)

def flowerGen(n):
  flwrs = Flower.__subclasses__()
  for i in range(n):
    yield random.choice(flwrs)()

# It's almost as if I had a method to Perform
# various "Bug" operations on all Flowers:
bee = Bee()
fly = Fly()
worm = Worm()
for flower in flowerGen(10):
  flower.accept(bee)
  flower.accept(fly)
  flower.accept(worm)
#:~