github地址:https://github.com/cheesezh/python_design_patterns

题目1

用程序模拟一个画小人的过程,要求小人要有头,身子,左手,右手,左脚,右脚。

基础代码

class PersonDrawer():

    def draw(self):
print("画头")
print("画身子")
print("画左手")
print("画右手")
print("画左脚")
print("画右脚") def main():
drawer = PersonDrawer()
drawer.draw() main()
画头
画身子
画左手
画右手
画左脚
画右脚

题目2

再画一个身子胖一些的小人。

class FatPersonDrawer():

    def draw(self):
print("画头")
print("画身子(胖一些)")
print("画左手")
print("画右手")
print("画右脚") def main():
drawer = FatPersonDrawer()
drawer.draw() main()
画头
画身子(胖一些)
画左手
画右手
画右脚

点评

画胖一些的小人时候,稍不注意,漏掉了左脚。画小人的步骤很繁琐,稍不注意就会漏掉一步,导致小人缺胳膊少腿。最好的办法就是规定,建造小人的时候,必须要有头,身子,左手,右手,左脚,右脚。这时候就可以使用建造这模式。

建造者模式

建造小人的过程是稳定的,都需要头身手脚,但是具体建造的细节是不同的,高矮胖瘦都有。

为了将一个复杂的对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示,就可以使用建造者模式,又叫“生成器模式”。

实现的方法就是定义抽象的建造者类,通过抽象函数的方法把构建的过程固定下来,这样就每一步也不能少,不会出现缺胳膊少腿的情况了。

from abc import ABCMeta, abstractmethod

class PersonBuilder():
"""
抽象建造者,定义创建对象各个部件的接口
"""
__metaclass__ = ABCMeta @abstractmethod
def draw_head(self):
pass @abstractmethod
def draw_body(self):
pass @abstractmethod
def draw_left_arm(self):
pass @abstractmethod
def draw_right_arm(self):
pass @abstractmethod
def draw_left_leg(self):
pass @abstractmethod
def draw_right_leg(self):
pass class ThinPersonBuilder(PersonBuilder):
"""
具体建造者,实现创建各个部件的接口
"""
def draw_head(self):
print("画头——瘦小人") def draw_body(self):
print("画身子——瘦小人") def draw_left_arm(self):
print("画左手——瘦小人") def draw_right_arm(self):
print("画右手——瘦小人") def draw_left_leg(self):
print("画左腿——瘦小人") def draw_rihgt_leg(self):
print("画右腿——瘦小人") class FatPersonBuilder(PersonBuilder):
"""
具体建造者,实现创建各个部件的接口
"""
def draw_head(self):
print("画头——胖小人") def draw_body(self):
print("画身子——胖小人") def draw_left_arm(self):
print("画左手——胖小人") def draw_right_arm(self):
print("画右手——胖小人") def draw_left_leg(self):
print("画左腿——胖小人") def draw_rihgt_leg(self):
print("画右腿——胖小人") class PersonDirector():
"""
指挥者,是构建一个使用Builder接口的对象
"""
def __init__(self, person_builder):
self.person_builder = person_builder def create_person(self):
self.person_builder.draw_head()
self.person_builder.draw_body()
self.person_builder.draw_left_arm()
self.person_builder.draw_right_arm()
self.person_builder.draw_left_leg()
self.person_builder.draw_right_leg() def main(): thin_person_builder = ThinPersonBuilder()
thin_person_director = PersonDirector(thin_person_builder)
thin_person_director.create_person() fat_person_builder = FatPersonBuilder()
fat_person_director = PersonDirector(fat_person_builder)
fat_person_director.create_person() main()
画头——瘦小人
画身子——瘦小人
画左手——瘦小人
画右手——瘦小人
画左腿——瘦小人
画头——胖小人
画身子——胖小人
画左手——胖小人
画右手——胖小人
画左腿——胖小人

点评

建造者模式的好处就是使得建造代码与表示代码分离,由于建造者隐藏了该产品是如何组装的,所以需要改变一个产品的内部表示,只需要再定义一个具体的建造者即可。

建造者模式是在当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时适用的模式。

[Python设计模式] 第13章 造小人——建造者模式的更多相关文章

  1. [Python设计模式] 第1章 计算器——简单工厂模式

    github地址:https://github.com/cheesezh/python_design_patterns 写在前面的话 """ 读书的时候上过<设计模 ...

  2. [Python设计模式] 第19章 分公司=部门?——组合模式

    github地址:https://github.com/cheesezh/python_design_patterns 组合模式 组合模式,将对象组合成树形结构以表示"部分-整体" ...

  3. 设计模式(五)Builder Pattern建造者模式

    在我们日常生活中,如构建一个飞船,一个手机,一栋建筑,都会有非常复杂的组装,这时候应该用到建造者模式 以建造一个飞船为例 案例:造小页飞船 1.飞船各部分元件 package com.littlepa ...

  4. 《大话设计模式》ruby版代码:建造者模式

    需求: 画一个小人,有头,有身体,两手两脚即可. 初始代码: # -*- encoding: utf-8 -*- #小人一 puts '这是第一个小人' puts '小人一:头' puts '小人一: ...

  5. 设计模式实战系列之@Builder和建造者模式

    前言 备受争议的Lombok,有的人喜欢它让代码更整洁,有的人不喜欢它,巴拉巴拉一堆原因.在我看来Lombok唯一的缺点可能就是需要安装插件了,但是对于业务开发的项目来说,它的优点远远超过缺点. 我们 ...

  6. .NET设计模式(13):享元模式(Flyweight Pattern)(转)

    摘要:面向对象的思想很好地解决了抽象性的问题,一般也不会出现性能上的问题.但是在某些情况下,对象的数量可能会太多,从而导致了运行时的代价.那么我们如何去避免大量细粒度的对象,同时又不影响客户程序使用面 ...

  7. [Python设计模式] 第21章 计划生育——单例模式

    github地址:https://github.com/cheesezh/python_design_patterns 单例模式 单例模式(Singleton Pattern)是一种常用的软件设计模式 ...

  8. [Python设计模式] 第22章 手机型号&软件版本——桥接模式

    github地址:https://github.com/cheesezh/python_design_patterns 紧耦合程序演化 题目1 编程模拟以下情景,有一个N品牌手机,在上边玩一个小游戏. ...

  9. [Python设计模式] 第16章 上班,干活,下班,加班——状态模式

    github地址:https://github.com/cheesezh/python_design_patterns 题目 用代码模拟一天的工作状态,上午状态好,中午想睡觉,下午渐恢复,加班苦煎熬. ...

随机推荐

  1. yield与yield from

    yield 通过yield返回的是一个生成器,yield既可以产出值又可以生成值,yield可以用next()来启动生成器,同时可以用send向生成器传递值:在初次启动生成器时,需调用next()或s ...

  2. LoadRunner录制协议的选择

    1.选择协议(提高测试结果的准确性) New Single Protocol Script:单协议脚本,选择一种主协议进行测试 New Multiple Protocol Script:多协议脚本,选 ...

  3. 总结TCP为什么三次握手四次挥手

    为什么三次握手,而不是两次或者四次五次? 2019/3/4更新: 在阅读了很多技术博客后,发先大家对为什么三次握手不是两次众说纷纭:我觉得说的最好的是英文文章对TCP的解读.TCP和UDP的区别就是可 ...

  4. union表关联模糊查询servlet,action方法

    2018-11-14 servletxml层 public String getSql(String keyword) { StringBuffer sqlSb = new StringBuffer( ...

  5. python inspect 模块 和 types 模块 判断是否是方法,模块,函数等内置特殊属性

    python inspect 模块 和 types 模块 判断是否是方法,模块,函数等内置特殊属性 inspect import inspect def fun(): pass inspect.ism ...

  6. img-html-2

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  7. POJ 2631 Roads in the North (模板题)(树的直径)

    <题目链接> 题目大意:求一颗带权树上任意两点的最远路径长度. 解题分析: 裸的树的直径,可由树形DP和DFS.BFS求解,下面介绍的是BFS解法. 在树上跑两遍BFS即可,第一遍BFS以 ...

  8. python MySQLdb 字段与关键字重名

    在做一个东西的时候,将字段命名为desc和describe. 构造sql语句并插入数据,报语法错误.一个一个字段排查,发现是这两个字段的问题. 找了一下,这两个是关键字. 所以,字段与关键字重名的时候 ...

  9. Windows下MySQL数据目录修改

    最近在弄一个项目,需要修改windows下面的mysql的数据目录(mysql默认是存储在C盘的,这个不太好,未来一定会满了的). 我的 mysql 是安装版,版本是 5.7. 1.首先,需要知道my ...

  10. Java 的Event机制浅析

    https://blog.csdn.net/kehyuanyu/article/details/23540901