原型模式是创建型模式中的最后一个,它主要用于对象创建成本比较大的情况。
本文UML类图链接为:https://www.processon.com/view/link/6080def6079129456d4beecf
本文代码链接为:https://github.com/shidawuhen/asap/blob/master/controller/design/10prototype.go
原型模式:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
UML类图:
UML图里的Client是客户端,可以不用管。对于Prototype,核心在于对象自身的Clone函数,用于拷贝自己。所以对于原型模式主要关注Clone函数即可,Clone可实现深拷贝或者浅拷贝。
至于是否需要有Prototype接口类,看具体情况,如果需要用到里氏替换,就创建接口类,如果没有用处,就无需创建。
原型模式主要用于创建对象成本较大的情况。如果创建对象极其方便,就不要用原型模式了,否则有过度设计、得不偿失之嫌。
一般使用在建立对象特别耗费资源,如需要从DB、硬盘等获取大量数据或者需要经过大量计算等;又或者建立的对象存储的内容是可以被复用,完全重新建一个新的更加耗时。
使用原型模式,需要了解深拷贝和浅拷贝。浅拷贝是指被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用都仍然指向原来的对象。深拷贝把引用对象的变量指向复制过的新对象,而不是原有的被引用的对象。在项目中使用深拷贝和还是浅拷贝,需要具体问题具体分析。
前些日子找工作的时候,使用了一款叫超级简历的APP,感觉挺符合原型模式的。编辑好一份简历后,可以生成副本,两份简历更改互不影响。因为对于不同的公司,简历表达侧重点不一样,但简历中很多内容都是可以复用的,所以副本这种操作很实用。
package main
import "fmt"
/**
* @Description: 简历类,里面包含简历的基本信息
*/
type Resume struct {
name string
age int64
sex string
company string
experience string
}
/**
* @Description: 设置简历个人信息
* @receiver r
* @param name
* @param age
* @param sex
*/
func (r *Resume) setPersonInfo(name string, age int64, sex string) {
r.name = name
r.age = age
r.sex = sex
}
/**
* @Description: 设置工作经验
* @receiver r
* @param company
* @param experience
*/
func (r *Resume) setWorkExperience(company string, experience string) {
r.company = company
r.experience = experience
}
/**
* @Description: 显示简历内容
* @receiver r
*/
func (r *Resume) display() {
fmt.Printf("我的名字是%s,性别%s,今年%d岁,在%s工作,工作经验为:%s \n", r.name, r.sex, r.age, r.company, r.experience)
}
/**
* @Description: 深拷贝,原型模式的核心
* @receiver r
* @return *Resume
*/
func (r *Resume) clone() *Resume {
return &Resume{
name: r.name,
sex: r.sex,
age: r.age,
company: r.company,
experience: r.experience,
}
}
func main() {
fmt.Println("---------------------------原简历")
resume := &Resume{
name: "王工作",
sex: "男",
age: 10,
company: "光明顶无限责任公司",
experience: "学武功和划水、摸鱼",
}
resume.display()
fmt.Println("---------------------------简历特别好,抄")
copyResume := resume.clone()
copyResume.setPersonInfo("李工作", 21, "男")
copyResume.display()
}
输出为:
➜ myproject go run main.go
---------------------------原简历
我的名字是王工作,性别男,今年10岁,在光明顶无限责任公司工作,工作经验为:学武功和划水、摸鱼
---------------------------简历特别好,抄
我的名字是李工作,性别男,今年21岁,在光明顶无限责任公司工作,工作经验为:学武功和划水、摸鱼
原型模式就是利用对已有对象(原型)进行复制(或者叫拷贝)的方式,来创建新对象,以达到节省创建时间的目的。拷贝可以选择深拷贝或者浅拷贝。
大家如果喜欢我的文章,可以关注我的公众号(程序员麻辣烫)
我的个人博客为:https://shidawuhen.github.io/
往期文章回顾:
招聘
字节跳动|抖音电商上海资深服务端开发工程师-交易
字节跳动|抖音电商武汉服务端(高级)开发工程师
字节跳动|飞书大客户产品经理内推咯
字节跳动|抖音电商服务端技术岗位虚位以待
字节跳动招聘专题
设计模式
Go设计模式(9)-建造者模式
Go设计模式(8)-抽象工厂
Go设计模式(7)-工厂模式
Go设计模式(6)-单例模式
Go设计模式(5)-类图符号表示法
Go设计模式(4)-代码编写优化
Go设计模式(4)-代码编写
Go设计模式(3)-设计原则
Go设计模式(2)-面向对象分析与设计
Go设计模式(1)-语法
语言
Go工具之generate
Go单例实现方案
Go通道实现原理
Go定时器实现原理
Beego框架使用
Golang源码BUG追查
Gin框架简洁版
Gin源码剖析
架构
支付接入常规问题
限流实现2
秒杀系统
分布式系统与一致性协议
微服务之服务框架和注册中心
浅谈微服务
限流实现1
CDN请求过程详解
常用缓存技巧
如何高效对接第三方支付
算法总结
存储
MySQL开发规范
Redis实现分布式锁
事务原子性、一致性、持久性的实现原理
InnoDB锁与事务简析
网络
HTTP2.0基础教程
HTTPS配置实战
HTTPS连接过程
TCP性能优化
工具
GoLand实用技巧
根据mysql表自动生成go struct
Markdown编辑器推荐-typora
读书笔记
《毛选》推荐
原则
资治通鉴
敏捷革命
如何锻炼自己的记忆力
简单的逻辑学-读后感
热风-读后感
论语-读后感
孙子兵法-读后感
思考
为动员一切力量争取胜利而斗争
反对自由主义
实践论
评价自己的标准
服务端团队假期值班方案
项目流程管理
对项目管理的一些看法
对产品经理的一些思考
关于程序员职业发展的思考
关于代码review的思考