Go设计模式(17)-享元模式
享元模式主要是为了复用对象,节省内存。使用享元模式需要有两个前提:
- 享元对象不可变:当享元模式创建出来后,它的变量和属性不会被修改
- 系统中存在大量重复对象:这些重复对象可以使用同一个享元,内存中只存在一份,这样会节省大量空间。当然这也是为什么享元对象不可变的原因,因为有很多引用,变更的话会引起很多问题。
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/
往期文章回顾:
招聘
- 字节跳动|内推大放送
- 字节跳动|今日头条广州服务端研发工程师内推
- 字节跳动|抖音电商急招上海前端开发工程
- 字节跳动|抖音电商上海资深服务端开发工程师-交易
- 字节跳动|抖音电商武汉服务端(高级)开发工程师
- 字节跳动|飞书大客户产品经理内推咯
- 字节跳动|抖音电商服务端技术岗位虚位以待
- 字节跳动招聘专题
设计模式
- Go设计模式(16)-组合模式
- Go设计模式(15)-门面模式
- Go设计模式(14)-适配器模式
- Go设计模式(13)-装饰器模式
- Go设计模式(12)-桥接模式
- Go设计模式(11)-代理模式
- Go设计模式(10)-原型模式
- Go设计模式(9)-建造者模式
- Go设计模式(8)-抽象工厂
- Go设计模式(7)-工厂模式
- Go设计模式(6)-单例模式
- Go设计模式(5)-类图符号表示法
- Go设计模式(4)-代码编写优化
- Go设计模式(4)-代码编写
- Go设计模式(3)-设计原则
- Go设计模式(2)-面向对象分析与设计
- Go设计模式(1)-语法
语言
- 再也不怕获取不到Gin请求数据了
- 一文搞懂pprof
- Go工具之generate
- Go单例实现方案
- Go通道实现原理
- Go定时器实现原理
- Beego框架使用
- Golang源码BUG追查
- Gin框架简洁版
- Gin源码剖析
架构
- 分页复选设计的坑
- 支付接入常规问题
- 限流实现2
- 秒杀系统
- 分布式系统与一致性协议
- 微服务之服务框架和注册中心
- 浅谈微服务
- 限流实现1
- CDN请求过程详解
- 常用缓存技巧
- 如何高效对接第三方支付
- 算法总结
存储
- 一文搞懂MySQL数据库分库分表
- MySQL开发规范
- Redis实现分布式锁
- 事务原子性、一致性、持久性的实现原理
- InnoDB锁与事务简析
网络
- HTTP2.0基础教程
- HTTPS配置实战
- HTTPS连接过程
- TCP性能优化
工具
- GoLand实用技巧
- 根据mysql表自动生成go struct
- Markdown编辑器推荐-typora
读书笔记
- 《毛选》推荐
- 原则
- 资治通鉴
- 敏捷革命
- 如何锻炼自己的记忆力
- 简单的逻辑学-读后感
- 热风-读后感
- 论语-读后感
- 孙子兵法-读后感
思考
- 对过去的一点回顾
- 对写博客的一些思考
- 晚上打119的经历
- 为动员一切力量争取胜利而斗争
- 反对自由主义
- 实践论
- 评价自己的标准
- 2020博客总结
- 服务端团队假期值班方案
- 项目流程管理
- 对项目管理的一些看法
- 对产品经理的一些思考
- 关于程序员职业发展的思考
- 关于代码review的思考
Go设计模式(17)-享元模式相关推荐
- 北风设计模式课程---享元模式
北风设计模式课程---享元模式 一.总结 一句话总结: 不仅要通过视频学,还要看别的博客里面的介绍,搜讲解,搜作用,搜实例 1.享元模式的本质是什么? 池技术:各种缓存池都是享元模式的体现 说到享元模 ...
- 每天一个设计模式之享元模式
作者按:<每天一个设计模式>旨在初步领会设计模式的精髓,目前采用javascript和python两种语言实现.诚然,每种设计模式都有多种实现方式,但此小册只记录最直截了当的实现方式 :) ...
- 北风设计模式课程---享元模式与单例模式区别
北风设计模式课程---享元模式与单例模式区别 一.总结 一句话总结: 不仅要通过视频学,还要看别的博客里面的介绍,搜讲解,搜作用,搜实例 1.享元模式与单例模式区别? 级别:单例模式是类级别的,一个类 ...
- .net设计模式 (享元模式)学习笔记
运用设计模式只是为了解决一类问题的,当解决掉当前一类问题,通常会在解决这个问题时候 带来其他问题 合理应用扬长避短 结构性设计模式:关注的是类与类之间的关系 .net设计模式 (享元模式)学习笔记 ...
- Java设计模式之享元模式(UML类图分析+代码详解)
大家好,我是一名在算法之路上不断前进的小小程序猿!体会算法之美,领悟算法的智慧~ 希望各位博友走过路过可以给我点个免费的赞,你们的支持是我不断前进的动力!! 加油吧!未来可期!! 本文将介绍java设 ...
- 详解设计模式:享元模式
享元模式(Flyweight Pattern),是对象池的一种体现,也是 GoF 的 23 种设计模式中的一种结构型设计模式. 享元模式 主要用于减少创建对象的数量,以减少内存占用和提高性能.它提供了 ...
- 设计模式之享元模式详解
设计模式之享元模式详解 概述 享元模式定义: 运用共享技术来有效地支持大量细粒度对象的复用.它==通过共享已经存在的对象来大幅度减少需要创建的对象数量==.避免大量相似对象的开销,从而提高系统资源 ...
- 【设计模式】享元模式(C#)
[设计模式]享元模式 1.概述 Flyweight Design Pattern,结构型模式.享元模式中的"享元"指被共享的单元.享元模式通过复用对象,以达到节省内存的目的. 用于 ...
- Java设计模式之享元模式
Java设计模式之享元模式 1. 享元模式概述 1.1 享元定义 1.2 享元模式注意事项 2. 享元模式实现 1. 享元模式概述 1.1 享元定义 1)享元模式(享元模式)也叫蝇量模式:利用共享技术 ...
最新文章
- 贪心算法之——喷水装置二(nyoj12)
- Python学习笔记:常用内建模块7XML
- python打包exe 之打包sklearn模型中的各种坑及其解决方法。
- switch 根据键盘录入成绩 显示分数及判断等级(第三次)
- java动态拼接String类sql
- 深度学习之基于InceptionV3实现水果识别
- 在线ajax测试,在线测试 - SosoApi,简单强大的api接口文档管理平台
- asp exce l连接字符串_C++基础知识篇:C++ 字符串
- [MFC] CDialog::DoModal()函数用法
- APScheduler——定时任务框架
- nlv sqlserver_SQLServer数据类型及使用分析
- aix c语言 构造函数,错误:命名构造函数,而不是类型。使用g++4.6.1进行编译
- idea 配置J2EE
- 215.数组中第的K个最大元素(力扣leetcode) 博主可答疑该问题
- windows下手动清理VMware卸载残留,解决卸载错误:the MSI failed
- 小记 -- cadence安装记录
- 计算机平面设计就业工资,cad制图工资一般多少
- 在vscode中打开PDF文件
- 微软的mak与kms区别
- 惠普服务器bios修改ilo,HPE Gen10 Plus iLO5 BIOS设置固定IP地址