国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

Go學設計模式--原型模式的考查點和使用推薦

開發 前端
在項目中使用原型模式時,可能需要在項目初始化時就把提供克隆能力的原型對象創建好,在多線程環境下,每個線程處理任務的時候,用到了相關對象,可以去原型對象那里拷貝。

前言

這篇原創本周發布過一次,名字和內容有些問題,不利于長期留存,重新整理發布一次。

如果一個類的有非常多的屬性,層級還很深。每次構造起來,不管是直接構造還是用建造者模式,都要對太多屬性進行復制,那么有沒有一種好的方式讓我們創建太的時候使用體驗更好一點呢? 今天的文章里就給大家介紹一種設計模式,來解決這個問題。

這篇內容要說的是創造型設計模式里的原型模式,如果寫過點 JS 代碼的話,大家可能聽說過原型鏈這么個東西,原型模式在 JavaScript 實現里確實廣泛應用,它那個面向對象跟 Java、C++ 這些語言的面向對象的實現方式還不太一樣,繼承其實是通過原型克隆出來,在拷貝出來的原型的基礎上再繼續添加或者修改來實現的。

什么是原型模式

通過復制、拷貝或者叫克隆已有對象的方式來創建新對象的設計模式叫做原型模式,被拷貝的對象也被稱作原型對象。

原型對象按照慣例,會暴露出一個 Clone 方法,給外部調用者一個機會來從自己這里“零成本”的克隆出一個新對象。

這里的“零成本”說的是,調用者啥都不用干,干等著,原型對象在 Clone 方法里自己克隆出自己,給到調用者,所以按照這個約定所有原型對象都要實現一個 Clone 方法。

type Prototype interface {
Clone() SpecificType
}

這里我們用UML類圖描述一下原型模式中各角色擁有的行為以及它們之間的關系

圖片

原型模式--UML類圖

至于原型對象克隆自己的時候用的是深拷貝還是淺拷貝?可以先理解成是都用深拷貝,等完全掌握這種思想后,可以再根據實際情況,比如為了節省空間、以及減少編寫克隆方法的復雜度時可以兩者綜合使用。

原型模式更多的是闡述一種編程模式,并沒有限制我們用什么方式實現。比如下面這個深拷貝和淺拷貝結合使用的例子。

// 示例代碼來自:https://lailin.xyz/post/prototype.html
package prototype

import (
"encoding/json"
"time"
)

// Keyword 搜索關鍵字
type Keyword struct {
word string
visit int
UpdatedAt *time.Time
}

// Clone 這里使用序列化與反序列化的方式深拷貝
func (k *Keyword) Clone() *Keyword {
var newKeyword Keyword
b, _ := json.Marshal(k)
json.Unmarshal(b, &newKeyword)
return &newKeyword
}

// Keywords 關鍵字 map
type Keywords map[string]*Keyword

// Clone 復制一個新的 keywords
// updatedWords: 需要更新的關鍵詞列表,由于從數據庫中獲取數據常常是數組的方式
func (words Keywords) Clone(updatedWords []*Keyword) Keywords {
newKeywords := Keywords{}

for k, v := range words {
// 這里是淺拷貝,直接拷貝了地址
newKeywords[k] = v
}

// 替換掉需要更新的字段,這里用的是深拷貝
for _, word := range updatedWords {
newKeywords[word.word] = word.Clone()
}

return newKeywords
}

使用原型模式的目的

使用原型模式的目的主要是為了節省創建對象所花費的時間和資源消耗,提升性能。

還有一點就是,比如全局配置對象這種也可以當成原型對象,如果不想讓程序在運行時修改初始化好的原型對象,導致影響其他線程的程序執行的時候,也可以用原型模式快速拷貝出一份,再在副本上做運行時自定義修改。

使用場景

當對象的創建成本比較大,并且同一個類的不同對象間差別不大時(大部分屬性值相同),如果對象的屬性值需要經過復雜的計算、排序,或者需要從網絡、DB等這些慢IO中獲取、亦或者或者屬性值擁有很深的層級,這時就是原型模式發揮作用的地方了。

因為對象在內存中復制自己遠比每次創建對象時重走一遍上面說的操作要來高效的多。

下面再來一個例子,讓我們更好的理解原型模式的優點。

利用原型模式實現文檔樹

下面是一個類似 DOM 樹對象的例子,因為 DOM 對象往往層級會很深,那么要創建類似的DOM樹的時候能讓我們更好的理解原型模式的優勢。

這個示例代碼來自:https://blog.ralch.com/articles/design-patterns/golang-prototype/

package dom

import (
"bytes"
"fmt"
)

// Node a document object model node
type Node interface {
// Strings returns nodes text representation
String() string
// Parent returns the node parent
Parent() Node
// SetParent sets the node parent
SetParent(node Node)
// Children returns the node children nodes
Children() []Node
// AddChild adds a child node
AddChild(child Node)
// Clone clones a node
Clone() Node
}

// Element represents an element in document object model
type Element struct {
text string
parent Node
children []Node
}

// NewElement makes a new element
func NewElement(text string) *Element {
return &Element{
text: text,
parent: nil,
children: make([]Node, 0),
}
}

// Parent returns the element parent
func (e *Element) Parent() Node {
return e.parent
}

// SetParent sets the element parent
func (e *Element) SetParent(node Node) {
e.parent = node
}

// Children returns the element children elements
func (e *Element) Children() []Node {
return e.children
}

// AddChild adds a child element
func (e *Element) AddChild(child Node) {
copy := child.Clone()
copy.SetParent(e)
e.children = append(e.children, copy)
}

// Clone makes a copy of particular element. Note that the element becomes a
// root of new orphan tree
func (e *Element) Clone() Node {
copy := &Element{
text: e.text,
parent: nil,
children: make([]Node, 0),
}
for _, child := range e.children {
copy.AddChild(child)
}
return copy
}

// String returns string representation of element
func (e *Element) String() string {
buffer := bytes.NewBufferString(e.text)

for _, c := range e.Children() {
text := c.String()
fmt.Fprintf(buffer, "\n %s", text)
}

return buffer.String()
}

上面的DOM對象-- Node、Element 這些都支持原型模式要求的 Clone 方法,那么有了這個原型克隆的能力后,假如我們想根據創建好的 DOM 樹上克隆出一個子分支作為一顆獨立的 DOM 樹對象的時候,就可以像下面這樣簡單地執行 Node.Clone() 把節點和其下面的子節點全部拷貝出去。比我們使用構造方法再重新構造樹形結構要方便許多。

下面的例子是用DOM樹結構創建一下公司里的職級關系,然后還可以從任意層級克隆出一顆新的樹。

func main() {
// 職級節點--總監
directorNode := dom.NewElement("Director of Engineering")
// 職級節點--研發經理
engManagerNode := dom.NewElement("Engineering Manager")
engManagerNode.AddChild(dom.NewElement("Lead Software Engineer"))
// 研發經理是總監的下級
directorNode.AddChild(engManagerNode)
directorNode.AddChild(engManagerNode)
// 辦公室經理也是總監的下級
officeManagerNode := dom.NewElement("Office Manager")
directorNode.AddChild(officeManagerNode)
fmt.Println("")
fmt.Println("# Company Hierarchy")
fmt.Print(directorNode)
fmt.Println("")
// 從研發經理節點克隆出一顆新的樹
fmt.Println("# Team Hiearachy")
fmt.Print(engManagerNode.Clone())
}
總結

總結

關于原型模式的總結,我們先來說一下原型模式的優缺點。

原型模式的優點

  • 某些時候克隆比直接new一個對象再逐屬性賦值的過程更簡潔高效,比如創建層級很深的對象的時候,克隆比直接用構造會方便很多。
  • 可以使用深克隆方式保存對象的狀態,可輔助實現撤銷操作。

原型模式的缺點

  • clone方法位于類的內部,當對已有類進行改造的時候,需要修改代碼,違背了開閉原則。
  • 當實現深克隆時,需要編寫較為復雜的代碼,尤其當對象之間存在多重嵌套引用時,為了實現深克隆,每一層對象對應的類都必須支持深克隆。因此,深克隆、淺克隆需要運用得當。

在項目中使用原型模式時,可能需要在項目初始化時就把提供克隆能力的原型對象創建好,在多線程環境下,每個線程處理任務的時候,用到了相關對象,可以去原型對象那里拷貝。不過適合當作原型對象的數據并不多,所以原型模式在開發中的使用頻率并不高,如果有機會做項目架構,可以適當考慮,確實需要再在項目中引入這種設計模式。

責任編輯:武曉燕 來源: 網管叨bi叨
相關推薦

2020-10-21 14:29:15

原型模式

2021-10-28 19:09:09

模式原型Java

2021-05-18 08:52:31

Prototype 原型模式設計模式

2013-11-26 17:00:08

Android設計模式

2023-08-08 20:13:36

設計模式原型模式

2020-08-03 08:24:26

原型模式拷貝

2015-06-08 09:05:10

Java原型模式

2021-06-07 09:51:22

原型模式序列化

2023-05-04 08:47:31

命令模式抽象接口

2023-04-10 09:20:13

設計模式訪客模式

2020-06-08 08:04:49

設計模式結構型接口

2024-12-27 15:10:16

設計模式原型模式場景

2023-05-15 08:51:46

解釋器模式定義

2023-05-26 08:41:23

模式Go設計模式

2025-01-20 09:03:41

項目Error優化

2023-01-09 08:43:53

Go設計模式

2022-12-26 08:54:02

Go設計模式接口,

2023-03-21 07:57:37

Go語言設計模式

2023-07-13 09:28:29

設計模式.NET

2023-03-27 00:20:48

點贊
收藏

51CTO技術棧公眾號

九色精品91| 最新中文字幕一区二区三区| 69久久夜色精品国产69乱青草| 超碰在线caoporen| 亚洲国产乱码最新视频| 久久精品免费网站| caoporen国产精品视频| 成人一区二区av| 激情文学综合丁香| 日本一区二区三区四区高清视频 | 欧美一区观看| 精品99视频| 国产亚洲精品久久飘花| 欧美二区视频| 成人午夜在线视频一区| 蜜桃精品wwwmitaows| 欧美性资源免费| 亚洲精品**不卡在线播he| 国内外成人免费激情在线视频| 天堂av一区| 久久免费精品日本久久中文字幕| 中文字幕亚洲在线观看| 欧美精品九九久久| 欧美一区二区三区红桃小说| 国内精品小视频| 久久99免费视频| 成人国产精品久久久| 狠狠干成人综合网| 日本公妇乱淫免费视频一区三区| 日韩中文欧美在线| 女女百合国产免费网站| av午夜一区麻豆| 已婚少妇美妙人妻系列| 国产精品国产馆在线真实露脸 | 伦理片一区二区三区| 一本大道久久a久久精品综合| 欧美18xxxxx| 欧美一区二区三区视频| 在线人成日本视频| 精品国产一区av| 亚洲区小说区图片区qvod| 成人免费视频97| 日本女人一区二区三区| 成人在线观看毛片| 国产精品国产三级国产有无不卡| 宅男宅女性影片资源在线1| 欧美日韩成人一区二区| 亚洲播播91| 97视频在线看| 亚洲女同中文字幕| 视频一区视频二区视频三区高| 国产一本一道久久香蕉| 九色91popny| 色就色 综合激情| 末成年女av片一区二区下载| 欧美日本亚洲视频| 欧美日韩国产精品一区二区亚洲| 在线看成人av电影| 亚洲私人影院在线观看| 日本视频在线观看| 久热精品在线视频| 综合久久精品| 激情六月天婷婷| 一区二区三区中文字幕精品精品 | 二吊插入一穴一区二区| 2018中文字幕一区二区三区| 激情久久久久久| 国产精品日韩三级| 午夜精品福利在线| 亚洲精品永久免费视频| 国产脚交av在线一区二区| 巨乳诱惑日韩免费av| 五月婷婷激情久久| 日韩一区二区三区免费看 | 传媒av在线| 亚洲免费视频网站| 久久资源中文字幕| 妞干网在线视频观看| 玉足女爽爽91| 日韩伦理在线一区| 国产主播精品在线| 成人av免费在线| 超碰在线国产| 久久久爽爽爽美女图片| 免费看精品久久片| 九色视频成人自拍| 久久久综合免费视频| 麻豆精品在线播放| 日本人妖在线| 国产91对白在线播放| 精品一区二区影视| 91涩漫在线观看| 日本欧美国产在线| www.欧美精品一二区| 欧美黄色视屏| 成人做爰66片免费看网站| 一区在线观看视频| 亚洲精品成人一区| 亚洲午夜精品一区二区| 欧美在线免费观看视频| 日本在线观看不卡| 国产日本欧洲亚洲| 日韩国产网站| 一本久久a久久精品vr综合| 狠狠干狠狠久久| 亚洲福利天堂| 精品久久久噜噜噜噜久久图片| 精品无码久久久久久国产| 激情综合网址| 日韩欧美在线观看一区二区| 日韩**中文字幕毛片| 久久婷婷综合激情| 成人一级视频| 国产日韩欧美大片| 欧美成人福利视频| 亚洲片区在线| 成人av毛片| 69堂成人精品视频免费| 亚洲国产成人av好男人在线观看| 女人抽搐喷水高潮国产精品| 久久久久久久久久久福利| 亚洲天堂精品在线| 国产在线一区二区综合免费视频| 青春草视频在线观看| 蜜桃狠狠色伊人亚洲综合网站| 欧美性猛交xxxx富婆弯腰| 91蜜臀精品国产自偷在线| 日本免费专区| 国产国语刺激对白av不卡| 亚洲精品综合在线| 欧美女优在线视频| h网址在线观看| 91精品视频播放| 欧美性猛交xxxx久久久| 一区二区三区中文| 77777影视视频在线观看| 久99久在线| 精品国产91乱码一区二区三区| 蜜臀久久99精品久久久久宅男 | 美女主播精品视频一二三四| 国产黄色特级片| 欧美激情一区二区三级高清视频| 国产日韩欧美综合一区| 1204国产成人精品视频| 91欧美视频在线| 日本一区二区三区在线播放| 亚洲经典视频| www.日本在线视频| 精品国产一区二区三区在线观看| 95精品视频在线| 久久久久高潮毛片免费全部播放| 初尝黑人巨炮波多野结衣电影| 国产精品视频26uuu| 在线观看成人小视频| 久久亚洲国产精品一区二区| 范冰冰一级做a爰片久久毛片| 男女日批视频在线观看| 欧美伦理91i| 亚洲综合男人的天堂| 欧美日韩国产欧| 国产理论电影在线| 黄色网页免费在线观看| 国产69精品久久久久久| 色婷婷综合久久久久中文一区二区 | 日本香蕉视频在线观看| 久久精品99久久久香蕉| 最新不卡av在线| 亚洲天堂免费| 天堂中文在线播放| 青青草精品视频在线观看| 国产精品96久久久久久| 337p亚洲精品色噜噜狠狠| 日韩综合一区二区| 欧美影院在线| 国产在线一二三区| 男人天堂网站在线| 日本三级久久久| 日韩三级精品电影久久久| 国产91综合一区在线观看| 精品影片在线观看的网站| 免费网站免费进入在线| 无码专区aaaaaa免费视频| 国产精品一区二区3区| 精品少妇一区二区三区 | 欧亚洲嫩模精品一区三区| 国产乱国产乱300精品| 天天做夜夜做人人爱精品| 欧美成人hd| 国产野外作爱视频播放| 国产日韩欧美精品| 欧美成aaa人片免费看| 在线欧美日韩国产| 成人av综合在线| 欧美成人一区二免费视频软件| 波多野结衣亚洲| 亚洲免费av一区二区| 黄网站欧美内射| 亚洲xxxxx性| 欧美人与性动交a欧美精品| 91麻豆精品国产91久久久|