创建一个集中式的系统来进行对象创建的一种方式就是使用工厂模式
原型模式与工厂模式的区别在于,原型模式不需要子类化,但是需要初始化操作,工厂模式不需要初始化操作,但是需要子类化。
先看看工厂方法的一个简单实现
import pygameclass Shape(object):def __init__(self, x, y):self.x = xself.y = ydef draw(self):raise NotImplementedErrordef move(self, direction):if direction == 'up':self.y -= 4if direction == 'down':self.y += 4if direction == 'left':self.x -= 4if direction == 'right':self.x += 4@staticmethoddef factory(type):if type == 'Circle':return Circle(100, 100)if type == 'Square':return Square(100, 100)assert 0, 'error shape requested:' + typeclass 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, 600screen = pygame.display.set_mode(windows_dimensions)player_quits = Falseobj = Shape.factory("Square")while not player_quits:for event in pygame.event.get():if event.type == pygame.QUIT:player_quits = Truepressed = 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 abcimport pygameclass AbstractFactory(object):__metaclass__ = abc.ABCMetadef __init__(self, x, y):self.x = xself.y = y@abc.abstractmethoddef make_object(self):returnclass 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 = xself.y = ydef draw(self):raise NotImplementedErrordef move(self, direction):if direction == 'up':self.y -= 4if direction == 'down':self.y += 4if direction == 'left':self.x -= 4if direction == 'right':self.x += 4class 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 drawabledef 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 drawableif __name__ == '__main__':windows_dimensions = 800, 600screen = pygame.display.set_mode(windows_dimensions)player_quits = Falseobj = prepare_client('s')while not player_quits:for event in pygame.event.get():if event.type == pygame.QUIT:player_quits = Truepressed = 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()
