原型模式

定义

如果对象的创建成本比较大,而同一个类的不同对象之间差别不大(大部分字段都相同),在这种情况下,我们可以利用对已有对象(原型)进行复制(或者叫拷贝)的方式来创建新对象,以达到节省创建时间的目的。这种基于原型来创建对象的方式就叫作原型设计模式(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. Java 知识点 列表

    * Java SE Java开发基础 Java异常处理 Java泛型与反射 Java IO基础 JUnit单元测试 Java多线程开发 Maven基础  https://www.yiibai.com/ ...

  2. 05-IdentityServer4

    前面我们认识了jwt的token颁发模式,其中的应用场景和部分缺陷已经很是了解了.有些场合并不适合jwt,特别是针对第三方进行使用时,比如我们使用qq或者微信登陆博客园或其他第三方应用时. Ids4的 ...

  3. LINUX系统入侵排查

    当企业发生黑客入侵.系统崩溃或其它影响业务正常运行的安全事件时,急需第一时间进行处理,使企业的网络信息系统在最短时间内恢复正常工作,进一步查找入侵来源,还原入侵事故过程,同时给出解决方案与防范措施,为 ...

  4. T-SQL——关于表数据的复制插入

    目录 0. 复制表中一列插入到另外一列 1. 复制表结构和数据到自动创建的一张新表中--select into 2. 复制表中一些字段值插入到另外一张表中--insert into 3. 将存储过过程 ...

  5. Apache ShardingSphere 元数据加载剖析

    唐国城 小米软件工程师,主要负责 MIUI 浏览器服务端研发工作.热爱开源,热爱技术,喜欢探索,热衷于研究学习各种开源中间件,很高兴能参与到 ShardingSphere 社区建设中,希望在社区中努力 ...

  6. 题解 [HAOI2016]字符合并

    题目传送门 Description 有一个长度为 \(n\) 的 \(01\) 串,你可以每次将相邻的 k 个字符合并,得到一个新的字符并获得一定分数. 得到的新字符和分数由这 k 个字符确定.你需要 ...

  7. GoLang设计模式10 - 中介者模式

    中介者模式是一种行为型设计模式.在中介者模式中创建了一个中介对象来负责不同类间的通信.因为这些类不需要直接交互,所以也就能避免它们之间的直接依赖,实现解耦的效果. 中介者模式的一个典型案例是老式小火车 ...

  8. Flutter随笔(二)——使用Flutter Web + Docker + Nginx打造一个简单的Web项目

    前言 Flutter作为一个跨平台UI框架,功能十分强大,仅用一套代码便能编译出Android.iOS.Web.windows.macOS.Windows.Linux等平台上的应用,各平台应用体验高度 ...

  9. 霍尔效应实验 execl数据处理

    execl 函数 =POWER() /*幂次*/ =ROUND() /*保留小数点后几位*/ =SQRT() /*开平方根*/ =POWER( x, 1/3 ) /*开立方根*/ =COUNTA() ...

  10. 【数据结构与算法Python版学习笔记】树——二叉树的应用:解析树

    解析树(语法树) 将树用于表示语言中句子, 可以分析句子的各种语法成分, 对句子的各种成分进行处理 语法分析树 程序设计语言的编译 词法.语法检查 从语法树生成目标代码 自然语言处理 机器翻译 语义理 ...