创建一个集中式的系统来进行对象创建的一种方式就是使用工厂模式
原型模式与工厂模式的区别在于,原型模式不需要子类化,但是需要初始化操作,工厂模式不需要初始化操作,但是需要子类化。
先看看工厂方法的一个简单实现
import pygame
class Shape(object):
def __init__(self, x, y):
self.x = x
self.y = y
def draw(self):
raise NotImplementedError
def move(self, direction):
if direction == 'up':
self.y -= 4
if direction == 'down':
self.y += 4
if direction == 'left':
self.x -= 4
if direction == 'right':
self.x += 4
@staticmethod
def factory(type):
if type == 'Circle':
return Circle(100, 100)
if type == 'Square':
return Square(100, 100)
assert 0, 'error shape requested:' + type
class Circle(Shape):
def draw(self):
pygame.draw.circle(
screen,
(255, 255, 0),
(self.x, self.y),
10
)
class Square(Shape):
def draw(self):
pygame.draw.rect(
screen,
(0, 255, 255),
pygame.Rect(self.x, self.y, 20, 20)
)
if __name__ == '__main__':
windows_dimensions = 800, 600
screen = pygame.display.set_mode(windows_dimensions)
player_quits = False
obj = Shape.factory("Square")
while not player_quits:
for event in pygame.event.get():
if event.type == pygame.QUIT:
player_quits = True
pressed = pygame.key.get_pressed()
if pressed[pygame.K_UP]: obj.move('up')
if pressed[pygame.K_DOWN]: obj.move('down')
if pressed[pygame.K_LEFT]: obj.move('left')
if pressed[pygame.K_RIGHT]: obj.move('right')
screen.fill((0, 0, 0))
obj.draw()
pygame.display.flip()
可以看到,采用上面的这段代码,将一个正方形变成一个圆形,或者变成我们想要的其他任何形状或图片,其处理是不是会容易的多?
无论何时,我们在游戏中添加一个需要在屏幕上绘制的新类, 只需要修改factory()即可
抽象工厂
当希望创建单个接口来访问整个工厂集合时, 可以毫无估计地使用一个抽象工厂,该集合中地每个抽象工厂都需要实现一个预定义接口,并且就每种工厂方法模式而言,该接口地每个函数都会返回另一个抽象类型
以下是代码示例
import abc
import pygame
class AbstractFactory(object):
__metaclass__ = abc.ABCMeta
def __init__(self, x, y):
self.x = x
self.y = y
@abc.abstractmethod
def make_object(self):
return
class CircleFactory(AbstractFactory):
def make_object(self):
return Circle(self.x, self.y)
class SquareFactory(AbstractFactory):
def make_object(self):
return Square(self.x, self.y)
class Shape(object):
def __init__(self, x, y):
self.x = x
self.y = y
def draw(self):
raise NotImplementedError
def move(self, direction):
if direction == 'up':
self.y -= 4
if direction == 'down':
self.y += 4
if direction == 'left':
self.x -= 4
if direction == 'right':
self.x += 4
class Circle(Shape):
def draw(self):
pygame.draw.circle(
screen,
(255, 255, 0),
(self.x, self.y),
10
)
class Square(Shape):
def draw(self):
pygame.draw.rect(
screen,
(0, 255, 255),
pygame.Rect(self.x, self.y, 20, 20)
)
def draw_function(factory):
drawable = factory.make_object()
drawable.draw()
return drawable
def prepare_client(type):
if type == 's':
square_factory = SquareFactory(200, 300)
drawable = draw_function(square_factory)
if type == 'c':
circle_factory = CircleFactory(100, 200)
drawable = draw_function(circle_factory)
return drawable
if __name__ == '__main__':
windows_dimensions = 800, 600
screen = pygame.display.set_mode(windows_dimensions)
player_quits = False
obj = prepare_client('s')
while not player_quits:
for event in pygame.event.get():
if event.type == pygame.QUIT:
player_quits = True
pressed = pygame.key.get_pressed()
if pressed[pygame.K_UP]: obj.move('up')
if pressed[pygame.K_DOWN]: obj.move('down')
if pressed[pygame.K_LEFT]: obj.move('left')
if pressed[pygame.K_RIGHT]: obj.move('right')
screen.fill((0, 0, 0))
obj.draw()
pygame.display.flip()