享元模式主要是为了复用对象,节省内存。使用享元模式需要有两个前提:

  1. 享元对象不可变:当享元模式创建出来后,它的变量和属性不会被修改
  2. 系统中存在大量重复对象:这些重复对象可以使用同一个享元,内存中只存在一份,这样会节省大量空间。当然这也是为什么享元对象不可变的原因,因为有很多引用,变更的话会引起很多问题。

UML类图位置:https://www.processon.com/diagraming/609b375407912943913a4c13

本文代码链接为:https://github.com/shidawuhen/asap/blob/master/controller/design/17flyweight.go

1.定义

1.1享元模式

享元模式:运用共享技术有效的支持大量细粒度的对象。

UML

1.2分析

享元模式主要是把系统中共同的、不变的对象抽象出来,达到共用一份的效果

抽象出的对象接口为Flyweight,ConcreteFlyweight为实际被共享的对象。UnsharedConcreteFlyweight是否存在,主要看是否有对象是无需共享的。

享元模式里有工厂FlyweightFactory,主要是因为系统中需要的享元结构虽然确定了,但是享元的属性不同,所以需要管理多个对象,此处使用了工厂模式。关于工厂模式可以参看这篇文章Go设计模式(7)-工厂模式。

2.使用场景

享元模式还是有很多具体使用场景的,如很多联网类棋牌游戏。假设有100w场象棋游戏在同时进行,不使用享元模式的话,系统需要维护32*100w个象棋对象。但象棋的文案、颜色、规则是不变的,变的只是持有人和位置。所以将32个象棋对象抽象出来,当做享元,可以极大的节省空间,而且不会带来成本提升。

享元模式与其说是一种设计模式,不如说是一种设计理念,主要讲的是抽象的能力,将相同模块提取出来,供不同模块使用。从这个维度来说,代码重构中提取相同功能、单例模式等,何尝不是另一种享元。

3.代码实现

写一下象棋游戏中对于象棋的管理吧。

package mainimport "fmt"/*** @Author: Jason Pang* @Description: 棋子类,有文案、颜色、规则,这三种不变属性*/
type Piece struct {text  stringcolor stringrule  string
}/*** @Author: Jason Pang* @Description: 棋子信息说明* @receiver p* @return string*/
func (p *Piece) String() string {return fmt.Sprintf("%s,颜色为%s,规则为%s", p.text, p.color, p.rule)
}/*** @Author: Jason Pang* @Description: 棋子在棋盘位置*/
type Pos struct {x int64y int64
}/*** @Author: Jason Pang* @Description: 游戏中的棋子*/
type GamePiece struct {piece   *Piece //棋子指针pos     Pos    //棋子位置ownerId int64  //玩家IDroomId  int64  //房间ID
}/*** @Author: Jason Pang* @Description: 游戏中的棋子说明* @receiver g* @return string*/
func (g *GamePiece) String() string {return fmt.Sprintf("%s位置为(%d,%d)", g.piece, g.pos.x, g.pos.y)
}/*** @Author: Jason Pang* @Description: 棋子工厂,包含32颗棋子信息*/
type PieceFactory struct {pieces []*Piece
}/*** @Author: Jason Pang* @Description: 创建棋子。棋子的信息都是不变的* @receiver f*/
func (f *PieceFactory) CreatePieces() {f.pieces = make([]*Piece, 32)f.pieces[0] = &Piece{text:  "兵",color: "红",rule:  "过河前只能一步一步前进,过河后只能一步一步前进或者左右移",}f.pieces[1] = &Piece{text:  "兵",color: "黑",rule:  "过河前只能一步一步前进,过河后只能一步一步前进或者左右移",}//todo 创建其它棋子。此处可以使用配置文件创建,能方便一些。系统中可以设置一个规则引擎,控制棋子运动。
}/*** @Author: Jason Pang* @Description: 获取棋子信息* @receiver f* @param id* @return *Piece*/
func (f *PieceFactory) GetPiece(id int64) *Piece {return f.pieces[id]
}/*** @Author: Jason Pang* @Description: 初始化棋盘* @param roomId* @param u1* @param u2*/
func InitBoard(roomId int64, u1 int64, u2 int64, factory *PieceFactory) {fmt.Printf("创建房间%d,玩家为%d和%d \n", roomId, u1, u2)fmt.Println("初始化棋盘")fmt.Printf("玩家%d的棋子为 \n", u1)piece := &GamePiece{piece:   factory.GetPiece(0),pos:     Pos{1, 1},roomId:  roomId,ownerId: u1,}fmt.Println(piece)fmt.Printf("玩家%d的棋子为 \n", u2)piece2 := &GamePiece{piece:   factory.GetPiece(1),pos:     Pos{16, 1},roomId:  roomId,ownerId: u2,}fmt.Println(piece2)
}
func main() {factory := &PieceFactory{}factory.CreatePieces()InitBoard(1, 66, 88, factory)
}

输出:

➜ myproject go run main.go

创建房间1,玩家为66和88

初始化棋盘

玩家66的棋子为

兵,颜色为红,规则为过河前只能一步一步前进,过河后只能一步一步前进或者左右移位置为(1,1)

玩家88的棋子为

兵,颜色为黑,规则为过河前只能一步一步前进,过河后只能一步一步前进或者左右移位置为(16,1)

3总结

享元模式充分说明了抽象的重要性,希望大家能够善用这种模式,优化系统。

最后

大家如果喜欢我的文章,可以关注我的公众号(程序员麻辣烫)

我的个人博客为:https://shidawuhen.github.io/

往期文章回顾:

招聘

  1. 字节跳动|内推大放送
  2. 字节跳动|今日头条广州服务端研发工程师内推
  3. 字节跳动|抖音电商急招上海前端开发工程
  4. 字节跳动|抖音电商上海资深服务端开发工程师-交易
  5. 字节跳动|抖音电商武汉服务端(高级)开发工程师
  6. 字节跳动|飞书大客户产品经理内推咯
  7. 字节跳动|抖音电商服务端技术岗位虚位以待
  8. 字节跳动招聘专题

设计模式

  1. Go设计模式(16)-组合模式
  2. Go设计模式(15)-门面模式
  3. Go设计模式(14)-适配器模式
  4. Go设计模式(13)-装饰器模式
  5. Go设计模式(12)-桥接模式
  6. Go设计模式(11)-代理模式
  7. Go设计模式(10)-原型模式
  8. Go设计模式(9)-建造者模式
  9. Go设计模式(8)-抽象工厂
  10. Go设计模式(7)-工厂模式
  11. Go设计模式(6)-单例模式
  12. Go设计模式(5)-类图符号表示法
  13. Go设计模式(4)-代码编写优化
  14. Go设计模式(4)-代码编写
  15. Go设计模式(3)-设计原则
  16. Go设计模式(2)-面向对象分析与设计
  17. Go设计模式(1)-语法

语言

  1. 再也不怕获取不到Gin请求数据了
  2. 一文搞懂pprof
  3. Go工具之generate
  4. Go单例实现方案
  5. Go通道实现原理
  6. Go定时器实现原理
  7. Beego框架使用
  8. Golang源码BUG追查
  9. Gin框架简洁版
  10. Gin源码剖析

架构

  1. 分页复选设计的坑
  2. 支付接入常规问题
  3. 限流实现2
  4. 秒杀系统
  5. 分布式系统与一致性协议
  6. 微服务之服务框架和注册中心
  7. 浅谈微服务
  8. 限流实现1
  9. CDN请求过程详解
  10. 常用缓存技巧
  11. 如何高效对接第三方支付
  12. 算法总结

存储

  1. 一文搞懂MySQL数据库分库分表
  2. MySQL开发规范
  3. Redis实现分布式锁
  4. 事务原子性、一致性、持久性的实现原理
  5. InnoDB锁与事务简析

网络

  1. HTTP2.0基础教程
  2. HTTPS配置实战
  3. HTTPS连接过程
  4. TCP性能优化

工具

  1. GoLand实用技巧
  2. 根据mysql表自动生成go struct
  3. Markdown编辑器推荐-typora

读书笔记

  1. 《毛选》推荐
  2. 原则
  3. 资治通鉴
  4. 敏捷革命
  5. 如何锻炼自己的记忆力
  6. 简单的逻辑学-读后感
  7. 热风-读后感
  8. 论语-读后感
  9. 孙子兵法-读后感

思考

  1. 对过去的一点回顾
  2. 对写博客的一些思考
  3. 晚上打119的经历
  4. 为动员一切力量争取胜利而斗争
  5. 反对自由主义
  6. 实践论
  7. 评价自己的标准
  8. 2020博客总结
  9. 服务端团队假期值班方案
  10. 项目流程管理
  11. 对项目管理的一些看法
  12. 对产品经理的一些思考
  13. 关于程序员职业发展的思考
  14. 关于代码review的思考

Go设计模式(17)-享元模式相关推荐

  1. 北风设计模式课程---享元模式

    北风设计模式课程---享元模式 一.总结 一句话总结: 不仅要通过视频学,还要看别的博客里面的介绍,搜讲解,搜作用,搜实例 1.享元模式的本质是什么? 池技术:各种缓存池都是享元模式的体现 说到享元模 ...

  2. 每天一个设计模式之享元模式

    作者按:<每天一个设计模式>旨在初步领会设计模式的精髓,目前采用javascript和python两种语言实现.诚然,每种设计模式都有多种实现方式,但此小册只记录最直截了当的实现方式 :) ...

  3. 北风设计模式课程---享元模式与单例模式区别

    北风设计模式课程---享元模式与单例模式区别 一.总结 一句话总结: 不仅要通过视频学,还要看别的博客里面的介绍,搜讲解,搜作用,搜实例 1.享元模式与单例模式区别? 级别:单例模式是类级别的,一个类 ...

  4. .net设计模式 (享元模式)学习笔记

    运用设计模式只是为了解决一类问题的,当解决掉当前一类问题,通常会在解决这个问题时候 带来其他问题  合理应用扬长避短 结构性设计模式:关注的是类与类之间的关系 .net设计模式 (享元模式)学习笔记 ...

  5. Java设计模式之享元模式(UML类图分析+代码详解)

    大家好,我是一名在算法之路上不断前进的小小程序猿!体会算法之美,领悟算法的智慧~ 希望各位博友走过路过可以给我点个免费的赞,你们的支持是我不断前进的动力!! 加油吧!未来可期!! 本文将介绍java设 ...

  6. 详解设计模式:享元模式

    享元模式(Flyweight Pattern),是对象池的一种体现,也是 GoF 的 23 种设计模式中的一种结构型设计模式. 享元模式 主要用于减少创建对象的数量,以减少内存占用和提高性能.它提供了 ...

  7. 设计模式之享元模式详解

    设计模式之享元模式详解 概述 享元模式定义: ​ 运用共享技术来有效地支持大量细粒度对象的复用.它==通过共享已经存在的对象来大幅度减少需要创建的对象数量==.避免大量相似对象的开销,从而提高系统资源 ...

  8. 【设计模式】享元模式(C#)

    [设计模式]享元模式 1.概述 Flyweight Design Pattern,结构型模式.享元模式中的"享元"指被共享的单元.享元模式通过复用对象,以达到节省内存的目的. 用于 ...

  9. Java设计模式之享元模式

    Java设计模式之享元模式 1. 享元模式概述 1.1 享元定义 1.2 享元模式注意事项 2. 享元模式实现 1. 享元模式概述 1.1 享元定义 1)享元模式(享元模式)也叫蝇量模式:利用共享技术 ...

最新文章

  1. 贪心算法之——喷水装置二(nyoj12)
  2. Python学习笔记:常用内建模块7XML
  3. python打包exe 之打包sklearn模型中的各种坑及其解决方法。
  4. switch 根据键盘录入成绩 显示分数及判断等级(第三次)
  5. java动态拼接String类sql
  6. 深度学习之基于InceptionV3实现水果识别
  7. 在线ajax测试,在线测试 - SosoApi,简单强大的api接口文档管理平台
  8. asp exce l连接字符串_C++基础知识篇:C++ 字符串
  9. [MFC] CDialog::DoModal()函数用法
  10. APScheduler——定时任务框架
  11. nlv sqlserver_SQLServer数据类型及使用分析
  12. aix c语言 构造函数,错误:命名构造函数,而不是类型。使用g++4.6.1进行编译
  13. idea 配置J2EE
  14. 215.数组中第的K个最大元素(力扣leetcode) 博主可答疑该问题
  15. windows下手动清理VMware卸载残留,解决卸载错误:the MSI failed
  16. 小记 -- cadence安装记录
  17. 计算机平面设计就业工资,cad制图工资一般多少
  18. 在vscode中打开PDF文件
  19. 微软的mak与kms区别
  20. 惠普服务器bios修改ilo,HPE Gen10 Plus iLO5 BIOS设置固定IP地址

热门文章

  1. Cesium中加载Geojson
  2. 3D 沙盒游戏之地面网格设计
  3. 前端优化——性能提升
  4. ASR PRO与 ESP8266 CP2102进行串口通信
  5. 开源的麦克纳姆轮全向移动机器人套件
  6. Python爬虫 | 全网资源汇总
  7. 【智能制造】索菲亚家居智能工厂与物流系统建设
  8. 初面蚂蚁金服,培训java知识
  9. android判断解锁,android判断手机SIM状态
  10. 操作系统面经总结—虚拟内存、内存分页、内存交换与覆盖等