当前位置:首页 > 公众号精选 > 码农爱学习

上篇文章,介绍了《大话设计模式》的第12章——外观模式。

本篇,来介绍《大话设计模式》的第13章——建造者模式。并通过python代码实现示例代码的功能。

1 建造者模式

建造者模式(Builder):将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

建造者模式的类图如下:

  • Builder:抽象建造类,定义建造一个产品所需要必要部件。
  • ConcreateBuilder:具体建造类,继承于抽象建造类,对抽象建造类中定义的接口进行实现,以实现个性化特征的产品构建。
  • Product:具体产品,具体建造类依赖于具体产品,即建造要根据产品功能来进行建造。
  • Director:指挥者类,控制建造的过程,确保建造过程中必要部件都执行了建造。

2 实例

背景:书中小故事,小菜和大鸟去饭店吃饭,分别点的炒面和炒饭,小菜的炒面吃着还不错,大鸟的炒饭味道不够,蛋也少。大鸟尝了一下炒面,味道不错,就又要了份炒面,结果,这炒面没放盐。。。回去的路上,大鸟感慨,肯德基、麦当劳能在中国发展的很好,大概是因为其制作过程规范严格,而中国的小吃,比如“鱼香肉丝”,不同的店可以吃出各种不同的口味。

启发:小吃店吃的味道怎么样,依赖于厨师。联想依赖倒转原则:抽象不应该依赖细节,细节应该依赖于抽象,由于吃的饭菜要依赖于厨师这样的细节,饭客就很被动。而像KFC那样,制作流程进行抽象,具体放什么配料、烤多长时间等细节依赖于这个抽象。

题目:根据流程的抽象原理,用代码的形式来实现用程序画不同体型的小人。

2.1 版本一:单独的类

版本一要实现画一个瘦的小人和一个胖的小人,通过分别定义这两个类来实现所需的功能。

2.1.1 瘦人和胖人类

这里通过Python编程来进行实践,使用pygame库中提供画图接口进行画图。

画一个廋的小人(ThinPerson),需要画出头(一个椭圆)、身体(一个矩形)、两个胳膊(线))、两条腿(线)

import pygame, sys

WHITE = (255, 255, 255)
BLUE = (0, 0, 255)

pygame.init()
screen = pygame.display.set_mode((200, 200))
screen.fill(WHITE)

class ThinPerson:
def draw_person(self):
pygame.draw.ellipse(screen,BLUE,(50,20,30,30),1)
pygame.draw.rect(screen,BLUE,(60, 50, 10, 50),1)
pygame.draw.line(screen,BLUE,(60, 50),(40, 100),1)
pygame.draw.line(screen,BLUE,(70, 50),(90, 100),1)
pygame.draw.line(screen,BLUE,(60, 100),(45, 150),1)
pygame.draw.line(screen,BLUE,(70, 100),(85, 150),1)

class FatPerson:
def draw_person(self):
pygame.draw.ellipse(screen,BLUE,(50,20,30,30),1)
pygame.draw.ellipse(screen,BLUE,(45,50,40,50),1)
pygame.draw.line(screen,BLUE,(50, 50),(30, 100),1)
pygame.draw.line(screen,BLUE,(80, 50),(100, 100),1)
pygame.draw.line(screen,BLUE,(60, 100),(45, 150),1)
#pygame.draw.line(screen,BLUE,(70, 100),(85, 150),1)

画一个胖的小人(FatPerson),也是类似的。不过这种方式,需要在编写代码的时候不要忘记小人的各个部分都要有,如果忘记了其中某些项,如忘记了画其中一条腿,最终画出来的小人就是不完整的。

2.1.2 主函数

首先,实例化对应的股票,

然后,就可以调用对应的买入和卖出的接口了。

thinPerson = ThinPerson() 
thinPerson.draw_person()

while True:
for e in pygame.event.get():
if e.type == pygame.QUIT:
pygame.quit()
sys.exit()
pygame.display.update()

画廋人的效果就是上面的那个图,画胖人的效果,如果忘记了画其中一条腿,将是下面的效果:

2.2 版本二:建造者模式

为了避免每增加一个新的不同特点的画小人的需求在实现时,可能忘记画小人的某一部分的问题,可以使用建造者模式。

画小人使用建造者模式,需要定义一个抽象类PersonBuilder,并声明画小人的各个部分的接口(声明为抽象接口,即继承的子类必须对接口进行对应的实现),具体不同特征的小人,各个部分的具体画法是怎样的,由具体建造者如画瘦人的ThinPersonBuilder和画胖人的FatPersonBuilder来进行各自的实现。

为了能确保不过是画廋人还是画胖人,各个部分都能画出而不遗漏,还需要一个指挥者PersonDirector,用它来控制建造过程。控制的原理是由它提供一个draw_person的接口,其内部统一进行绘制小人身体的各个部分。

修改后的代码如下:

class PersonBuilder(ABC):
@abstractmethod
def build_head(self):
pass

@abstractmethod
def build_body(self):
pass

@abstractmethod
def build_arm_left(self):
pass

@abstractmethod
def build_arm_right(self):
pass

@abstractmethod
def build_leg_left(self):
pass

@abstractmethod
def build_leg_right(self):
pass

class PersonDirector():
def __init__(self,personBuilder):
self.pb
= personBuilder

def draw_person(self):
self.pb.build_head()
self.pb.build_body()
self.pb.build_arm_left()
self.pb.build_arm_right()
self.pb.build_leg_left()
self.pb.build_leg_right()

class ThinPersonBuilder(PersonBuilder):
def build_head(self):
pygame.draw.ellipse(screen,BLUE,(50,20,30,30),1)

def build_body(self):
pygame.draw.rect(screen,BLUE,(60, 50, 10, 50),1)

def build_arm_left(self):
pygame.draw.line(screen,BLUE,(60, 50),(40, 100),1)

def build_arm_right(self):
pygame.draw.line(screen,BLUE,(70, 50),(90, 100),1)

def build_leg_left(self):
pygame.draw.line(screen,BLUE,(60, 100),(45, 150),1)

def build_leg_right(self):
pygame.draw.line(screen,BLUE,(70, 100),(85, 150),1)

class FatPersonBuilder(PersonBuilder):
def build_head(self):
pygame.draw.ellipse(screen,BLUE,(50,20,30,30),1)

def build_body(self):
pygame.draw.ellipse(screen,BLUE,(45,50,40,50),1)

def build_arm_left(self):
pygame.draw.line(screen,BLUE,(50, 50),(30, 100),1)

def build_arm_right(self):
pygame.draw.line(screen,BLUE,(80, 50),(100, 100),1)

def build_leg_left(self):
pygame.draw.line(screen,BLUE,(60, 100),(45, 150),1)
"""
def build_leg_right(self):
pygame.draw.line(screen,BLUE,(70, 100),(85, 150),1)
"""

thinPerson
= ThinPersonBuilder()
#fatPerson = FatPersonBuilder()
personDirector = PersonDirector(thinPerson)
personDirector.draw_person()

使用建造者模式后,因为绘制小人的各个部分是由指挥者PersonDirector来控制绘制的,因此不会出现某个部位的绘制遗漏,如果某个具体建造者忘记了对其某个部分的绘制进行重写,在编译运行时就会报错,例如画胖人时忘记了画右腿:

总结

本篇介绍了设计模式中的建造者模式,并通过画小人的实例,使用Python编程,来演示建造者模式的使用。

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除( 邮箱:macysun@21ic.com )。
关闭