原型模式

定义

如果对象的创建成本比较大,而同一个类的不同对象之间差别不大(大部分字段都相同),在这种情况下,我们可以利用对已有对象(原型)进行复制(或者叫拷贝)的方式来创建新对象,以达到节省创建时间的目的。这种基于原型来创建对象的方式就叫作原型设计模式(Prototype Design Pattern),简称原型模式。

原型模式是能基于拷贝来的,对于拷贝我们知道有两种形式,深拷贝和浅拷贝

浅拷贝只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存。但深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象。

原型模式浅拷贝:

1、省内存,拷贝时间更快;

2、浅拷贝容易出现原始数据被修改的情况,一般不建议使用;

3、浅拷贝可以拷贝不可变对象;

原型模式深拷贝:

1、数据完全隔离;

2、不过数据量大的情况下,深拷贝比起浅拷贝来说,更加耗时,更加耗内存空间;

代码实现

// Cloneable 是原型对象需要实现的接口
type Cloneable interface {
Clone() Cloneable
} type PrototypeManager struct {
prototypes map[string]Cloneable
} func NewPrototypeManager() *PrototypeManager {
return &PrototypeManager{
prototypes: make(map[string]Cloneable),
}
} func (p *PrototypeManager) Get(name string) Cloneable {
return p.prototypes[name].Clone()
} func (p *PrototypeManager) Set(name string, prototype Cloneable) {
p.prototypes[name] = prototype
}

测试文件

var (
deepCopyManager *PrototypeManager
shallowCopyManager *PrototypeManager
) // 深拷贝实现Cloneable
type DeepCopy struct {
name string
} func (t *DeepCopy) Clone() Cloneable {
tc := *t
return &tc
} // 浅拷贝实现Cloneable
type ShallowCopy struct {
name string
} func (t *ShallowCopy) Clone() Cloneable {
return t
} func TestDeepCopyClone(t *testing.T) {
t1 := deepCopyManager.Get("dc") t2 := t1.Clone()
// 深拷贝,指向的不是同一个变量的地址
if t1 == t2 {
t.Fatal("error! get clone not working")
} t21 := t2.(*DeepCopy)
t21.name = "ShallowCopy-test" t11 := t1.(*DeepCopy)
// 深拷贝name,不会影响到copy前的变量
if t11.name == t21.name {
t.Fatal("shallowCopy err")
}
} func TestShallowCopyClone(t *testing.T) {
t1 := shallowCopyManager.Get("sc") t2 := t1.Clone()
// 浅拷贝,变量地址的指向不变
if t1 != t2 {
t.Fatal("error! get clone not working")
} t21 := t2.(*ShallowCopy)
t21.name = "ShallowCopy-test" t11 := t1.(*ShallowCopy)
// 深拷贝name,copy之前的变量和copy之后的变量同时更改
if t11.name != t21.name {
t.Fatal("shallowCopy err")
}
} func init() {
deepCopyManager = NewPrototypeManager() dc := &DeepCopy{
name: "deepCopy",
}
deepCopyManager.Set("dc", dc) shallowCopyManager = NewPrototypeManager()
sc := &ShallowCopy{
name: "shallowCopy",
}
shallowCopyManager.Set("sc", sc)
}

优点

1、使用原型模式创建对象比直接new一个对象在性能上要好的多,因为是直接进行的内存拷贝,比初始化性能上会好很多;

2、简化对象的创建,对于创建对象就像我们在编辑文档时的复制粘贴一样简单。

缺点

克隆包含循环引用的复杂对象可能会非常麻烦。

适用场景

1、在项目中,如果存在大量相同或相似对象的创建,如果用传统的构造函数来创建对象,会比较复杂和耗费资源,用原型模式生产对象就很高效;

2、对象创建过程比较麻烦,但复制比较简单的时候;

参考

【文中代码】https://github.com/boilingfrog/design-pattern-learning/tree/master/原型模式

【大话设计模式】https://book.douban.com/subject/2334288/

【极客时间】https://time.geekbang.org/column/intro/100039001

【原型模式】https://github.com/senghoo/golang-design-pattern

【原文地址】https://boilingfrog.github.io/2021/11/08/使用go实现原型模式/

设计模式学习-使用go实现原型模式的更多相关文章

  1. C#设计模式学习笔记:(5)原型模式

    本笔记摘抄自:https://www.cnblogs.com/PatrickLiu/p/7640873.html,记录一下学习过程以备后续查用.  一.引言 很多人说原型设计模式会节省机器内存,他们说 ...

  2. 设计模式之第9章-原型模式(Java实现)

    设计模式之第9章-原型模式(Java实现) “快到春节了,终于快放假了,天天上班好累的说.”“确实啊,最近加班比较严重,项目快到交付了啊.”“话说一到过节,就收到铺天盖地的短信轰炸,你说发短信就发吧, ...

  3. .NET设计模式(6):原型模式(Prototype Pattern)(转)

    概述 在软件系统中,有时候面临的产品类是动态变化的,而且这个产品类具有一定的等级结构.这时如果用工厂模式,则与产品类等级结构平行的工厂方法类也要随着这种变化而变化,显然不大合适.那么如何封装这种动态的 ...

  4. .NET设计模式(6):原型模式(Prototype Pattern)

    ):原型模式(Prototype Pattern)    );         //使用颜色         string colorName = "red";         C ...

  5. 设计模式总结篇系列:原型模式(Prototype)

    首先对原型模式进行一个简单概念说明:通过一个已经存在的对象,复制出更多的具有与此对象具有相同类型的新的对象. 在理解Java原型模式之前,首先需要理解Java中的一个概念:复制/克隆. 在博文< ...

  6. Java 设计模式系列(五)原型模式

    Java 设计模式系列(五)原型模式 原型模式属于对象的创建模式.通过给出一个原型对象来指明所有创建的对象的类型,然后用复制这个原型对象的办法创建出更多同类型的对象.这就是选型模式的用意. 一.原型模 ...

  7. Java设计模式学习笔记(二) 简单工厂模式

    前言 本篇是设计模式学习笔记的其中一篇文章,如对其他模式有兴趣,可从该地址查找设计模式学习笔记汇总地址 正文开始... 1. 简介 简单工厂模式不属于GoF23中设计模式之一,但在软件开发中应用也较为 ...

  8. Java设计模式学习笔记(三) 工厂方法模式

    前言 本篇是设计模式学习笔记的其中一篇文章,如对其他模式有兴趣,可从该地址查找设计模式学习笔记汇总地址 1. 简介 上一篇博客介绍了简单工厂模式,简单工厂模式存在一个很严重的问题: 就是当系统需要引入 ...

  9. Java设计模式学习笔记(四) 抽象工厂模式

    前言 本篇是设计模式学习笔记的其中一篇文章,如对其他模式有兴趣,可从该地址查找设计模式学习笔记汇总地址 1. 抽象工厂模式概述 工厂方法模式通过引入工厂等级结构,解决了简单工厂模式中工厂类职责太重的问 ...

随机推荐

  1. 华为云计算IE面试笔记-FusionCompute虚拟机热迁移定义,应用场景,迁移要求,迁移过程

    *热迁移传送了什么数据?保存在哪? 虚拟机的内存.虚拟机描述信息(配置和设备信息).虚拟机的状态 虚拟机的配置和设备信息:操作系统(类别.版本号).引导方式(VM通过硬盘.光盘.U盘.网络启动)和引导 ...

  2. vue 熟悉项目结构 创建第一个自己的组件

    * vue开发环境搭建 * 项目入口文件 ./src/main.js // The Vue build version to load with the `import` command // (ru ...

  3. redis linux的 安装

    https://blog.csdn.net/u011159417/article/details/80085011 安装: 1.获取redis资源 wget http://download.redis ...

  4. Charles抓包工具断点修改返回内容

    在测试过程中,往往需要让服务器返回指定的内容,测试一些特殊情况.例如列表内容为空.数据异常的情况等.如果通过操作服务器配合构造相应的数据会比较麻烦,甚至不好构造数据.此时,可以使用Charles的断点 ...

  5. AT4518-[AGC032C]Three Circuits【欧拉回路】

    正题 题目链接:https://www.luogu.com.cn/problem/AT4518 题目大意 给出\(n\)个点\(m\)条边的一张简单无向联通图,求能否把它分成三个可重复点的环. \(1 ...

  6. Spring Cloud Gateway 雪崩了,我 TM 人傻了

    本系列是 我TM人傻了 系列第六期[捂脸],往期精彩回顾: 升级到Spring 5.3.x之后,GC次数急剧增加,我TM人傻了 这个大表走索引字段查询的 SQL 怎么就成全扫描了,我TM人傻了 获取异 ...

  7. jQuery实现购物车功能

    1.HTML代码(品优购模版) <!DOCTYPE html> <html lang="zh-CN"> <head> <meta char ...

  8. 【死磕NIO】— 阻塞IO,非阻塞IO,IO复用,信号驱动IO,异步IO,这你真的分的清楚吗?

    通过上篇文章([死磕NIO]- 阻塞.非阻塞.同步.异步,傻傻分不清楚),我想你应该能够区分了什么是阻塞.非阻塞.异步.非异步了,这篇文章我们来彻底弄清楚什么是阻塞IO,非阻塞IO,IO复用,信号驱动 ...

  9. redis 5.0.12 install

    redis 5.0.12 install ## check directory ls -l /XXXXXXX ##create dir mkdir -p /XXXXXXX/dataredis mkdi ...

  10. 从工具、工具箱到数字化软件工厂——DevOps 设计理念与工程实践专场 | CIF 精彩看点

    西方经典管理理论认为,组织效率可以归为劳动效率.组织效率和人的效率.美国管理学家泰勒所著的<科学管理原理>被德鲁克誉为"20 世纪最伟大的发明",劳动效率说认为分工提升 ...