加入星计划,您可以享受以下权益:

  • 创作内容快速变现
  • 行业影响力扩散
  • 作品版权保护
  • 300W+ 专业用户
  • 1.5W+ 优质创作者
  • 5000+ 长期合作伙伴
立即加入
  • 正文
    • 1 建造者模式
    • 2 实例
    • 总结
  • 相关推荐
申请入驻 产业图谱

《大话设计模式》解读09-建造者模式

2024/12/31
379
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

上篇文章,介绍了《大话设计模式》的第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编程,来演示建造者模式的使用。

文章推荐

《大话设计模式》解读01-简单工厂模式

《大话设计模式》解读02-策略模式

《大话设计模式》解读03-装饰模式

《大话设计模式解读》04-代理模式

《大话设计模式》解读05-工厂方法

《大话设计模式》解读06-原型模式

《大话设计模式》解读07-模板方法

《大话设计模式》解读08-外观模式

相关推荐

登录即可解锁
  • 海量技术文章
  • 设计资源下载
  • 产业链客户资源
  • 写文章/发需求
立即登录