Prototype mode
definition
If the cost of creating objects is relatively large, and there is little difference between different objects of the same class (most fields are the same), in this case, we can create new objects by copying (or copying) existing objects (prototypes), so as to save creation time. This method of creating objects based on prototypes is called Prototype Design Pattern, which is called prototype pattern for short.
Prototype mode can be based on copy. We know that there are two forms of copy, deep copy and shallow copy
Shallow copy only copies the pointer to an object, not the object itself. The old and new objects still share the same block of memory. But deep copy as like as two peas will create another object that is exactly the same. New objects do not share memory with original objects, and new objects will not be changed to original objects.
Prototype mode shallow copy:
1. Save memory and faster copy time;
2. Shallow copy is easy to modify the original data, which is generally not recommended;
3. Shallow copy can copy immutable objects;
Prototype mode deep copy:
1. Complete data isolation;
2. However, when there is a large amount of data, deep copy is more time-consuming and memory space consuming than shallow copy;
code implementation
// Clonable is the interface that the prototype object needs to implement 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 }
Test file
var ( deepCopyManager *PrototypeManager shallowCopyManager *PrototypeManager ) // Deep copy implementation clonable type DeepCopy struct { name string } func (t *DeepCopy) Clone() Cloneable { tc := *t return &tc } // Shallow copy implementation clonable type ShallowCopy struct { name string } func (t *ShallowCopy) Clone() Cloneable { return t } func TestDeepCopyClone(t *testing.T) { t1 := deepCopyManager.Get("dc") t2 := t1.Clone() // Deep copy refers to an address that is not the same variable if t1 == t2 { t.Fatal("error! get clone not working") } t21 := t2.(*DeepCopy) t21.name = "ShallowCopy-test" t11 := t1.(*DeepCopy) // Deep copy name will not affect the variables before copy if t11.name == t21.name { t.Fatal("shallowCopy err") } } func TestShallowCopyClone(t *testing.T) { t1 := shallowCopyManager.Get("sc") t2 := t1.Clone() // For shallow copy, the direction of variable address remains unchanged if t1 != t2 { t.Fatal("error! get clone not working") } t21 := t2.(*ShallowCopy) t21.name = "ShallowCopy-test" t11 := t1.(*ShallowCopy) // Deep copy name, variables before copy and variables after copy are changed at the same time 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) }
advantage
1. Using prototype mode to create an object is much better than directly new an object, because it is a direct memory copy, which is much better than initialization;
2. Simplify the creation of objects. Creating objects is as simple as copying and pasting when editing documents.
shortcoming
Cloning complex objects with circular references can be cumbersome.
Applicable scenario
1. In the project, if there are a large number of identical or similar objects, it will be more complex and resource consuming to create objects with traditional constructors. It is very efficient to produce objects with prototype mode;
2. Object creation is troublesome, but copying is simple;
reference resources
[code in text] https://github.com/boilingfrog/design-pattern-learning/tree/master/ Prototype mode
[big talk design mode] https://book.douban.com/subject/2334288/
[geek time] https://time.geekbang.org/column/intro/100039001
[prototype mode] https://github.com/senghoo/golang-design-pattern
[original address] https://boilingfrog.github.io/2021/11/08/ Using go to implement prototype pattern/