创建一个集中式的系统来进行对象创建的一种方式就是使用工厂模式

原型模式与工厂模式的区别在于,原型模式不需要子类化,但是需要初始化操作,工厂模式不需要初始化操作,但是需要子类化。
先看看工厂方法的一个简单实现

  1. import pygame
  2. class Shape(object):
  3. def __init__(self, x, y):
  4. self.x = x
  5. self.y = y
  6. def draw(self):
  7. raise NotImplementedError
  8. def move(self, direction):
  9. if direction == 'up':
  10. self.y -= 4
  11. if direction == 'down':
  12. self.y += 4
  13. if direction == 'left':
  14. self.x -= 4
  15. if direction == 'right':
  16. self.x += 4
  17. @staticmethod
  18. def factory(type):
  19. if type == 'Circle':
  20. return Circle(100, 100)
  21. if type == 'Square':
  22. return Square(100, 100)
  23. assert 0, 'error shape requested:' + type
  24. class Circle(Shape):
  25. def draw(self):
  26. pygame.draw.circle(
  27. screen,
  28. (255, 255, 0),
  29. (self.x, self.y),
  30. 10
  31. )
  32. class Square(Shape):
  33. def draw(self):
  34. pygame.draw.rect(
  35. screen,
  36. (0, 255, 255),
  37. pygame.Rect(self.x, self.y, 20, 20)
  38. )
  39. if __name__ == '__main__':
  40. windows_dimensions = 800, 600
  41. screen = pygame.display.set_mode(windows_dimensions)
  42. player_quits = False
  43. obj = Shape.factory("Square")
  44. while not player_quits:
  45. for event in pygame.event.get():
  46. if event.type == pygame.QUIT:
  47. player_quits = True
  48. pressed = pygame.key.get_pressed()
  49. if pressed[pygame.K_UP]: obj.move('up')
  50. if pressed[pygame.K_DOWN]: obj.move('down')
  51. if pressed[pygame.K_LEFT]: obj.move('left')
  52. if pressed[pygame.K_RIGHT]: obj.move('right')
  53. screen.fill((0, 0, 0))
  54. obj.draw()
  55. pygame.display.flip()

可以看到,采用上面的这段代码,将一个正方形变成一个圆形,或者变成我们想要的其他任何形状或图片,其处理是不是会容易的多?
无论何时,我们在游戏中添加一个需要在屏幕上绘制的新类, 只需要修改factory()即可

抽象工厂

当希望创建单个接口来访问整个工厂集合时, 可以毫无估计地使用一个抽象工厂,该集合中地每个抽象工厂都需要实现一个预定义接口,并且就每种工厂方法模式而言,该接口地每个函数都会返回另一个抽象类型
以下是代码示例

  1. import abc
  2. import pygame
  3. class AbstractFactory(object):
  4. __metaclass__ = abc.ABCMeta
  5. def __init__(self, x, y):
  6. self.x = x
  7. self.y = y
  8. @abc.abstractmethod
  9. def make_object(self):
  10. return
  11. class CircleFactory(AbstractFactory):
  12. def make_object(self):
  13. return Circle(self.x, self.y)
  14. class SquareFactory(AbstractFactory):
  15. def make_object(self):
  16. return Square(self.x, self.y)
  17. class Shape(object):
  18. def __init__(self, x, y):
  19. self.x = x
  20. self.y = y
  21. def draw(self):
  22. raise NotImplementedError
  23. def move(self, direction):
  24. if direction == 'up':
  25. self.y -= 4
  26. if direction == 'down':
  27. self.y += 4
  28. if direction == 'left':
  29. self.x -= 4
  30. if direction == 'right':
  31. self.x += 4
  32. class Circle(Shape):
  33. def draw(self):
  34. pygame.draw.circle(
  35. screen,
  36. (255, 255, 0),
  37. (self.x, self.y),
  38. 10
  39. )
  40. class Square(Shape):
  41. def draw(self):
  42. pygame.draw.rect(
  43. screen,
  44. (0, 255, 255),
  45. pygame.Rect(self.x, self.y, 20, 20)
  46. )
  47. def draw_function(factory):
  48. drawable = factory.make_object()
  49. drawable.draw()
  50. return drawable
  51. def prepare_client(type):
  52. if type == 's':
  53. square_factory = SquareFactory(200, 300)
  54. drawable = draw_function(square_factory)
  55. if type == 'c':
  56. circle_factory = CircleFactory(100, 200)
  57. drawable = draw_function(circle_factory)
  58. return drawable
  59. if __name__ == '__main__':
  60. windows_dimensions = 800, 600
  61. screen = pygame.display.set_mode(windows_dimensions)
  62. player_quits = False
  63. obj = prepare_client('s')
  64. while not player_quits:
  65. for event in pygame.event.get():
  66. if event.type == pygame.QUIT:
  67. player_quits = True
  68. pressed = pygame.key.get_pressed()
  69. if pressed[pygame.K_UP]: obj.move('up')
  70. if pressed[pygame.K_DOWN]: obj.move('down')
  71. if pressed[pygame.K_LEFT]: obj.move('left')
  72. if pressed[pygame.K_RIGHT]: obj.move('right')
  73. screen.fill((0, 0, 0))
  74. obj.draw()
  75. pygame.display.flip()