• 设计模式学习使用go实现原型模式 Zhan


    原型模式

    定义

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

  • 相关阅读:
    MySQL的语句执行顺序
    mysql 基本使用
    spring 事务详解
    java 设计模式
    hibernate 简单查询
    qwq(一些有趣的数学题)
    关于libra9z
    HDU6756 Finding a MEX
    CF1386C Joker
    CF1340F Nastya and CBS
  • 原文地址:https://www.cnblogs.com/ricklz/p/15525612.html
Copyright © 2020-2023  润新知