声明:本系列文章主要参考《精通Python设计模式》一书,并且参考一些资料,结合自己的一些看法来总结而来。

  享元模式:

  享元模式是一种用于解决资源和性能压力时会使用到的设计模式,它的核心思想是通过引入数据共享来提升性能

  在开发3D游戏时,例如有成千上万的士兵或者有成千上万棵树,如果一个3D地带的每个对象都单独创建,不使用数据共享,那么性能是无法接受的。

  故享元设计模式就是通过为相似对象映入数据共享来最小化内存的使用,提升性能。

  既然要创建成千上万个士兵,那么若他们的数据属性行为都是一样的,那岂不是黏一块去了。这时候就会有:可变数据和不可变数据的概念。

  即 -- 重点在于将不可变(可共享)的属性与可变的属性区分开。相同类型的对象共享不可变(可共享)的数据,而每个对象又有其独立的数据,这部分数据即为:可变的属性(不可共享数据)。

  实现:

  其实享元模式的实现与单例模式的实现方式十分相似,比如:单例模式实现的是一个类对象只允许有一个实例对象,而享元模式则是一个类对象只允许创建不同类型的对象,这样保证同一类型的对象共享不可变数据。

  直接看书中代码吧:

  1. from enum import Enum
  2.  
  3. TreeType = Enum('TreeType','apple_tree cherry_tree peach_tree')
  4.  
  5. class Tree:
  6. pool = dict()
  7.  
  8. def __new__(cls, tree_type, *args,**kwargs):
  9. obj = cls.pool.get(tree_type,None)
  10. if not obj:
  11. obj = super().__new__(cls,*args, **kwargs)
  12. cls.pool[tree_type] = obj
  13. obj.tree_type = tree_type
  14. return obj
  15.  
  16. def __init(self,size ):
  17. self.size = size
  18.  
  19. def render(self,age,x,y):
  20. print('render a tree of type {} and age {} at ({},{})'.format(self.tree_type,age,x,y))

  这样就实现了一个简单的享元模式:即通过其中的__new__魔法方法来限制类的实例化,只允许实例化不同类型的对象。

  通过一个类型池,若需要实例化的类型在该类型池中,则直接返回该类型池中的对象,由于返回的是同一对象,故其共享不可变的属性(tree_type),而在执行完成__new__()方法之后,变化执行__init__魔法方法,则这时候该对象的属性便会发生改变,故不共享可变的属性(size)。

  既然我们实现了一个简单的享元模式,那么怎么去使用它呢?

  1. import random
  2. from enum import Enum
  3.  
  4. def main():
  5. rnd = random.Random()
  6. age_min, age_max = 1, 30
  7. min_piont, max_point = 0, 100
  8. tree_counter = 0
  9.  
  10. for _ in range(10):
  11. t1 = Tree(TreeType.apple_tree)
  12. t1.render(rnd.randint(age_min, age_max),
  13. rnd.randint(min_piont, max_point),
  14. rnd.randint(min_piont, max_point)
  15. )
  16. tree_counter += 1
  17.  
  18. for _ in range(3):
  19. t1 = Tree(TreeType.cherry_tree)
  20. t1.render(rnd.randint(age_min, age_max),
  21. rnd.randint(min_piont, max_point),
  22. rnd.randint(min_piont, max_point)
  23. )
  24. tree_counter += 1
  25.  
  26. for _ in range(5):
  27. t1 = Tree(TreeType.peach_tree)
  28. t1.render(rnd.randint(age_min, age_max),
  29. rnd.randint(min_piont, max_point),
  30. rnd.randint(min_piont, max_point)
  31. )
  32. tree_counter += 1
  33.  
  34. print(Tree.pool)
  35.  
  36. if __name__ == '__main__':
  37. main()

  在main()中去创建10棵apple_tree,并且 为每个对象随机给不同的年龄、位置等,这样就可以在游戏中的不同的位置中渲染。

  输出结果为:

  1. render a tree of type TreeType.apple_tree and age 17 at (48,57)
  2. render a tree of type TreeType.apple_tree and age 30 at (27,9)
  3. render a tree of type TreeType.apple_tree and age 4 at (74,92)
  4. render a tree of type TreeType.apple_tree and age 16 at (8,95)
  5. render a tree of type TreeType.apple_tree and age 26 at (43,95)
  6. render a tree of type TreeType.apple_tree and age 1 at (80,20)
  7. render a tree of type TreeType.apple_tree and age 26 at (21,88)
  8. render a tree of type TreeType.apple_tree and age 22 at (53,57)
  9. render a tree of type TreeType.apple_tree and age 17 at (65,47)
  10. render a tree of type TreeType.apple_tree and age 24 at (34,77)
  11. render a tree of type TreeType.cherry_tree and age 18 at (71,41)
  12. render a tree of type TreeType.cherry_tree and age 30 at (63,33)
  13. render a tree of type TreeType.cherry_tree and age 13 at (56,53)
  14. render a tree of type TreeType.peach_tree and age 27 at (44,80)
  15. render a tree of type TreeType.peach_tree and age 21 at (29,60)
  16. render a tree of type TreeType.peach_tree and age 14 at (62,52)
  17. render a tree of type TreeType.peach_tree and age 20 at (37,63)
  18. render a tree of type TreeType.peach_tree and age 7 at (30,8)
  19. {<TreeType.apple_tree: 1>: <__main__.Tree object at 0x00000253D1183AC8>,
  20. <TreeType.cherry_tree: 2>: <__main__.Tree object at 0x00000253D1187080>,
  21. <TreeType.peach_tree: 3>: <__main__.Tree object at 0x00000253D1187978>}

  其实可以发现同一类型的树对象,其ID均一样,而其size属性却不一样,这是由于在执行__init__方法时,返回类型池中的对象后,在进行初始化会size属性会覆盖前面返回的对象的size属性值。

  总结:

  该示例中,在__new__方法中实现类不可变数据的共享。

       在__init__方法中实现了可变数据的独立,即不共享。

  over~~~

浅谈Python设计模式 - 享元模式的更多相关文章

  1. 浅谈js设计模式 — 享元模式

    享元(flyweight)模式是一种用于性能优化的模式,“fly”在这里是苍蝇的意思,意为蝇量级.享元模式的核心是运用共享技术来有效支持大量细粒度的对象. 假设有个内衣工厂,目前的产品有 50种男式内 ...

  2. 浅谈Python设计模式 -- 责任链模式

    声明:本系列文章主要参考<精通Python设计模式>一书,并且参考一些资料,结合自己的一些看法来总结而来. 之前在最开始就聊了Python设计模式有三种,其中关于创建型和结构型设计模式基本 ...

  3. 浅谈Python设计模式 - 抽象工厂模式

    声明:本系列文章主要参考<精通Python设计模式>一书,并且参考一些资料,结合自己的一些看法来总结而来. 在上一篇我们对工厂模式中的普通工厂模式有了一定的了解,其实抽象工作就是 表示针对 ...

  4. 大话设计模式Python实现- 享元模式

    享元模式(Flyweight Pattern):运用共享技术有效地支持大量细粒度的对象. 下面是一个享元模式的demo: #!/usr/bin/env python # -*- coding:utf- ...

  5. 8. 星际争霸之php设计模式--享元模式

    题记==============================================================================本php设计模式专辑来源于博客(jymo ...

  6. C++设计模式——享元模式

    本文版权归果冻说所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接,否则保留追究法律责任的权利.如果这篇文章对你有帮助,你可以请我喝杯咖啡. » 本文链接:http:// ...

  7. java设计模式——享元模式

    一. 定义与类型 定义:提供了减少对象数量从而改善应用所需的对象结构的方式,运用共享技术有效地支持大量细粒度的对象 类型:结构性 二. 使用场景 (1)  常常应用于系统底层的开发,以便解决系统的性能 ...

  8. 【设计模式】Java设计模式 - 享元模式

    Java设计模式 - 享元模式 不断学习才是王道 继续踏上学习之路,学之分享笔记 总有一天我也能像各位大佬一样 原创作品,更多关注我CSDN: 一个有梦有戏的人 准备将博客园.CSDN一起记录分享自己 ...

  9. [工作中的设计模式]享元模式模式FlyWeight

    一.模式解析 Flyweight在拳击比赛中指最轻量级,即“蝇量级”或“雨量级”,这里选择使用“享元模式”的意译,是因为这样更能反映模式的用意.享元模式是对象的结构模式.享元模式以共享的方式高效地支持 ...

随机推荐

  1. 微信网页分享使用了jssdk,分享图还是不显示的几个坑

    坑爹的微信分享,设置图片链接必须要满足如下条件: 1. 微信分享图链接必须是绝对路径,写相对地址不行. 比如图片地址写成 './assets/images/share.jpg' 不行!!! 必须写成 ...

  2. CF1208F Bits And Pieces

    CF1208F Bits And Pieces 传送门 思路 这里要运用SOS-DP的思路(\(\text{Sum over Subsets}\)).我在另外一篇博客里介绍过,如有需要可以搜索一下我的 ...

  3. AppDomin学习与分享

    最近学习并分享了appdomin的一些东西,以前没怎么记录过,现在记录一下吧2016-03-17 什么是AppDomin •全称:Application Domin(应用程序域) •定义:AppDom ...

  4. Java集合详解1:一文读懂ArrayList,Vector与Stack使用方法和实现原理

    本文非常详尽地介绍了Java中的三个集合类 ArrayList,Vector与Stack <Java集合详解系列>是我在完成夯实Java基础篇的系列博客后准备开始写的新系列. 这些文章将整 ...

  5. Azure容器监控部署(下)

    上文已经基本完成了环境的搭建,prometheus可以以https的方式从node_exporter和cAdvisor上pull到数据,访问grafana时也可以以https的方式访问,安全性得到了一 ...

  6. maven 依赖优化

    1.mvn dependency:list  列出项目用到的依赖 2.查看依赖树 mvn dependency:tree 3.mvn dependency:analyze Used undeclare ...

  7. 公司某台电脑连接服务器共享文件失败(Windows找不到"\\192.168.1.3)

    电脑键入“\\192.168.1.3”后报错“Windows找不到"\\192.168.1.3".请检查拼写并重试.” 我做了两步: 1.检查网络发现是否开启: 控制面板---&g ...

  8. Linux重启Mysql命令

  9. k8s部署nacos之二 nfs

    1.在linux服务器下载nacos 首先安装git命令 yum install git git clone https://github.com/nacos-group/nacos-k8s.git ...

  10. asp获取access数据库中的一条随机记录

    针对“用一条SQL得到数据库中的随机记录集”问题在网上已经有很多答案了: SQL Server 2000: SELECT TOP n * FROM tanblename ORDER BY NEWID( ...