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. linux抓包工具Charles的配置安装

    1. 安装 (不赘述,方法很多,我使用yaourt charles安装) 2. 导出证书,crt格式保存备用 3. 浏览器导入证书 4. 浏览器设置代理

  2. 阿里 EasyExcel 使用及避坑

    github地址:https://github.com/alibaba/easyexcel 原本在项目中使用EasyPoi读取excel,后来为了统一技术方案,改用阿里的EasyExcel.EasyE ...

  3. 用单向链表实现两数倒序相加(java实现)

    很久没做算法题了,准备重操旧业,于是刷了一波LeetCode,看到一个比较经典的链表算法题,分享出来. 题目 给定两个非空链表来表示两个非负整数.位数按照逆序方式存储,它们的每个节点只存储单个数字.将 ...

  4. 其实我们可以少写点if else和switch

    前言 作为搬砖在第一线的底层工人,业务场景从来是没有做不到只有想不到的复杂. 不过他强任他强,if-else全搞定,搬就完了.但是随着业务迭代或者项目交接,自己在看自己或者别人的if代码的时候,心情就 ...

  5. Codeforces Round #530 (Div. 2)

    RANK :2252 题数 :3 补题: D - Sum in the tree 思路:贪心 把权值放在祖先节点上 ,预处理 每个节点保存 他与他儿子中 权值最小值即可. 最后会有一些叶子节点依旧为 ...

  6. XamarinSQLite教程创建数据库

    XamarinSQLite教程创建数据库 安装SQLite/SQL Server Compact Toolbox后,就可以使用该插件创建数据库了.操作步骤如下: (1)在Visual Studio中, ...

  7. WPF DataGrid 每行ComboBox 内容不同的设置方法

    <toolkit:DataGridComboBoxColumn x:Name="DgCbcSignal" Header="信号源" SelectedIte ...

  8. mysql存储引擎的优缺点

    不同的存储引擎都有各自的特点,以适应不同的需求,如下表所示: 功  能 MYISAM Memory InnoDB Archive 存储限制 256TB RAM 64TB None 支持事物 No No ...

  9. 元素 "context:component-scan" 的前缀 "context" 未绑定。

    是因为没有导入context的命名空间

  10. 深入理解JVM(9)——类加载的过程

    加载是类加载的第一步. 一.加载 a)加载的过程 1)通过一个类的全限定名获取这个类的二进制字节流,也就是class文件 2)将二进制字节流的存储结构转换为特定的数据结构,存储在方法区 3)在内存中创 ...