fork download
  1. #!/usr/bin/env python
  2.  
  3. from abc import ABCMeta, abstractmethod
  4.  
  5. def subclasshook(required):
  6. """Generates a subclass hook based on a simple check for attributes."""
  7. def __subclasshook__(cls, Check):
  8. rtn = True
  9. for r in required:
  10. if not any(r in vars(BaseClass) for BaseClass in Check.__mro__):
  11. rtn = NotImplemented
  12. return rtn
  13. return __subclasshook__
  14.  
  15. class Duck(object):
  16. def __init__(self, fly, quack):
  17. self._fly_behaviour = fly
  18. self._quack_behaviour = quack
  19.  
  20. def fly(self):
  21. return self._fly_behaviour.fly()
  22.  
  23. def quack(self):
  24. return self._quack_behaviour.quack()
  25.  
  26. def swim(self):
  27. print "All ducks float, even decoys!"
  28.  
  29. class MallardDuck(Duck):
  30. def __init__(self):
  31. Duck.__init__(self, Fly(), Quack())
  32. print "I'm a real Mallard Duck"
  33.  
  34. class ModelDuck(Duck):
  35. def __init__(self):
  36. Duck.__init__(self, FlyNoWay(), SqueakQuack())
  37. print "I'm a Model Duck"
  38.  
  39. class DecoyDuck(Duck):
  40. def __init__(self):
  41. Duck.__init__(self, FlyNoWay(), MuteQuack())
  42. print "I'm a Decoy Duck"
  43.  
  44. class FlyBehavior:
  45. __metaclass__ = ABCMeta
  46.  
  47. @abstractmethod
  48. def fly(self):
  49. pass
  50.  
  51. __subclasshook__ = classmethod(subclasshook(["fly"]))
  52.  
  53. class Fly(FlyBehavior):
  54. def fly(self):
  55. print "I'm flying!!"
  56.  
  57. class FlyNoWay(FlyBehavior):
  58. def fly(self):
  59. print "I can't fly"
  60.  
  61. class FlyRocketPowered(FlyBehavior):
  62. def fly(self):
  63. print "I'm flying with a rocket!"
  64.  
  65. class QuackBehavior:
  66. __metaclass__ = ABCMeta
  67.  
  68. @abstractmethod
  69. def quack(self):
  70. pass
  71.  
  72. __subclasshook__ = classmethod(subclasshook(["quack"]))
  73.  
  74. class Quack(QuackBehavior):
  75. def quack(self):
  76. print "Quack"
  77.  
  78. class MuteQuack(QuackBehavior):
  79. def quack(self):
  80. print "<< Silence >>"
  81.  
  82. class SqueakQuack(QuackBehavior):
  83. def quack(self):
  84. print "Squeak"
  85.  
  86. if __name__ == "__main__":
  87.  
  88. print '#'*80
  89. print "Mallard Duck"
  90. print '#'*80
  91. mallard = MallardDuck()
  92. mallard.quack()
  93. mallard.fly()
  94.  
  95. print '#'*80
  96. print "Model Duck"
  97. print '#'*80
  98. model = ModelDuck()
  99. model.fly()
  100. model._fly_behaviour = FlyRocketPowered()
  101. model.fly()
  102.  
  103. print '#'*80
  104. print "Decoy Duck"
  105. print '#'*80
  106. decoy = DecoyDuck()
  107. decoy.fly()
  108. decoy.quack()
Success #stdin #stdout 0.08s 10824KB
stdin
Standard input is empty
stdout
################################################################################
Mallard Duck
################################################################################
I'm a real Mallard Duck
Quack
I'm flying!!
################################################################################
Model Duck
################################################################################
I'm a Model Duck
I can't fly
I'm flying with a rocket!
################################################################################
Decoy Duck
################################################################################
I'm a Decoy Duck
I can't fly
<< Silence >>