最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Go設(shè)計(jì)模式原型模式考查點(diǎn)及使用詳解

 更新時(shí)間:2022年12月09日 15:54:13   作者:kevinyan  
這篇文章主要為大家介紹了Go設(shè)計(jì)模式原型模式考查點(diǎn)及使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

前言

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

這篇內(nèi)容要說的是創(chuàng)造型設(shè)計(jì)模式里的原型模式,如果寫過點(diǎn) JS 代碼的話,大家可能聽說過原型鏈這么個(gè)東西,原型模式在 JavaScript 實(shí)現(xiàn)里確實(shí)廣泛應(yīng)用,它那個(gè)面向?qū)ο蟾?Java、C++ 這些語言的面向?qū)ο蟮膶?shí)現(xiàn)方式還不太一樣,繼承其實(shí)是通過原型克隆出來,在拷貝出來的原型的基礎(chǔ)上再繼續(xù)添加或者修改來實(shí)現(xiàn)的。

什么是原型模式

通過復(fù)制、拷貝或者叫克隆已有對象的方式來創(chuàng)建新對象的設(shè)計(jì)模式叫做原型模式,被拷貝的對象也被稱作原型對象。

原型對象按照慣例,會(huì)暴露出一個(gè) Clone 方法,給外部調(diào)用者一個(gè)機(jī)會(huì)來從自己這里“零成本”的克隆出一個(gè)新對象。

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

type Prototype interface {
    Clone() SpecificType
}

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

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

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

// 示例代碼來自:https://lailin.xyz/post/prototype.html
package prototype
import (
	"encoding/json"
	"time"
)
// Keyword 搜索關(guān)鍵字
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 關(guān)鍵字 map
type Keywords map[string]*Keyword
// Clone 復(fù)制一個(gè)新的 keywords
// updatedWords: 需要更新的關(guān)鍵詞列表,由于從數(shù)據(jù)庫中獲取數(shù)據(jù)常常是數(shù)組的方式
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
}

使用原型模式的目的

使用原型模式的目的主要是為了節(jié)省創(chuàng)建對象所花費(fèi)的時(shí)間和資源消耗,提升性能。

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

使用場景

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

因?yàn)閷ο笤趦?nèi)存中復(fù)制自己遠(yuǎn)比每次創(chuàng)建對象時(shí)重走一遍上面說的操作要來高效的多。

下面再來一個(gè)例子,讓我們更好的理解原型模式的優(yōu)點(diǎn)。

利用原型模式實(shí)現(xiàn)文檔樹

下面是一個(gè)類似 DOM 樹對象的例子,因?yàn)?DOM 對象往往層級會(huì)很深,那么要?jiǎng)?chuàng)建類似的DOM樹的時(shí)候能讓我們更好的理解原型模式的優(yōu)勢。

這個(gè)示例代碼來自:blog.ralch.com/articles/de…

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 方法,那么有了這個(gè)原型克隆的能力后,假如我們想根據(jù)創(chuàng)建好的 DOM 樹上克隆出一個(gè)子分支作為一顆獨(dú)立的 DOM 樹對象的時(shí)候,就可以像下面這樣簡單地執(zhí)行 Node.Clone() 把節(jié)點(diǎn)和其下面的子節(jié)點(diǎn)全部拷貝出去。比我們使用構(gòu)造方法再重新構(gòu)造樹形結(jié)構(gòu)要方便許多。

下面的例子是用DOM樹結(jié)構(gòu)創(chuàng)建一下公司里的職級關(guān)系,然后還可以從任意層級克隆出一顆新的樹。

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

總結(jié)

關(guān)于原型模式的總結(jié),我們先來說一下原型模式的優(yōu)缺點(diǎn)。

原型模式的優(yōu)點(diǎn)

  • 某些時(shí)候克隆比直接new一個(gè)對象再逐屬性賦值的過程更簡潔高效,比如創(chuàng)建層級很深的對象的時(shí)候,克隆比直接用構(gòu)造會(huì)方便很多。
  • 可以使用深克隆方式保存對象的狀態(tài),可輔助實(shí)現(xiàn)撤銷操作。

原型模式的缺點(diǎn)

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

在項(xiàng)目中使用原型模式時(shí),可能需要在項(xiàng)目初始化時(shí)就把提供克隆能力的原型對象創(chuàng)建好,在多線程環(huán)境下,每個(gè)線程處理任務(wù)的時(shí)候,用到了相關(guān)對象,可以去原型對象那里拷貝。不過適合當(dāng)作原型對象的數(shù)據(jù)并不多,所以原型模式在開發(fā)中的使用頻率并不高,如果有機(jī)會(huì)做項(xiàng)目架構(gòu),可以適當(dāng)考慮,確實(shí)需要再在項(xiàng)目中引入這種設(shè)計(jì)模式。

以上就是Go設(shè)計(jì)模式原型模式考查點(diǎn)及使用詳解的詳細(xì)內(nèi)容,更多關(guān)于Go原型模式考查點(diǎn)的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Go語言并發(fā)編程之互斥鎖Mutex和讀寫鎖RWMutex

    Go語言并發(fā)編程之互斥鎖Mutex和讀寫鎖RWMutex

    Go 語言中提供了很多同步工具,本文將介紹互斥鎖Mutex和讀寫鎖RWMutex的使用方法,想要具體了解的小伙伴,請參考下面文章詳細(xì)內(nèi)容,希望對你有所幫助
    2021-10-10
  • golang 解析word文檔操作

    golang 解析word文檔操作

    這篇文章主要介紹了golang 解析word文檔操作,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • Go接口的用法詳解

    Go接口的用法詳解

    本文主要介紹了Go接口的用法詳解,包括定義接口、實(shí)現(xiàn)接口、使用接口、空接口等,通過接口,可以實(shí)現(xiàn)多態(tài)性,即一個(gè)對象可以實(shí)現(xiàn)多個(gè)接口,從而實(shí)現(xiàn)不同接口的行為,感興趣的可以了解一下
    2023-11-11
  • 詳解minio分布式文件存儲(chǔ)

    詳解minio分布式文件存儲(chǔ)

    MinIO 是一款基于 Go 語言的高性能、可擴(kuò)展、云原生支持、操作簡單、開源的分布式對象存儲(chǔ)產(chǎn)品,這篇文章主要介紹了minio分布式文件存儲(chǔ),需要的朋友可以參考下
    2023-10-10
  • GO excelize讀取excel進(jìn)行時(shí)間類型轉(zhuǎn)換的示例代碼(自動(dòng)轉(zhuǎn)換)

    GO excelize讀取excel進(jìn)行時(shí)間類型轉(zhuǎn)換的示例代碼(自動(dòng)轉(zhuǎn)換)

    我們經(jīng)常會(huì)遇到如何自動(dòng)識別excel中的時(shí)間類型數(shù)據(jù)并轉(zhuǎn)化成對應(yīng)的 "Y-m-d H:i:s"類型數(shù)據(jù),本文小編給大家介紹了GO excelize讀取excel進(jìn)行時(shí)間類型轉(zhuǎn)換的示例代碼(自動(dòng)轉(zhuǎn)換),需要的朋友可以參考下
    2024-10-10
  • go語言實(shí)現(xiàn)順序存儲(chǔ)的棧

    go語言實(shí)現(xiàn)順序存儲(chǔ)的棧

    這篇文章主要介紹了go語言實(shí)現(xiàn)順序存儲(chǔ)的棧,實(shí)例分析了Go語言實(shí)現(xiàn)順序存儲(chǔ)的棧的原理與各種常見的操作技巧,需要的朋友可以參考下
    2015-03-03
  • golang中實(shí)現(xiàn)給gif、png、jpeg圖片添加文字水印

    golang中實(shí)現(xiàn)給gif、png、jpeg圖片添加文字水印

    這篇文章主要介紹了golang中實(shí)現(xiàn)給gif、png、jpeg圖片添加文字水印,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-04-04
  • golang對etcd存取和數(shù)值監(jiān)測的實(shí)現(xiàn)

    golang對etcd存取和數(shù)值監(jiān)測的實(shí)現(xiàn)

    這篇文章主要介紹了golang對etcd存取和數(shù)值監(jiān)測的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09
  • golang語言http協(xié)議get拼接參數(shù)操作

    golang語言http協(xié)議get拼接參數(shù)操作

    這篇文章主要介紹了golang語言http協(xié)議get拼接參數(shù)操作,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • 一文帶你了解Go語言中鎖特性和實(shí)現(xiàn)

    一文帶你了解Go語言中鎖特性和實(shí)現(xiàn)

    Go語言中的sync包主要提供的對并發(fā)操作的支持,標(biāo)志性的工具有cond(條件變量)?once?(原子性)?還有?鎖,本文會(huì)主要向大家介紹Go語言中鎖的特性和實(shí)現(xiàn),感興趣的可以了解下
    2024-03-03

最新評論

申扎县| 东山县| 萍乡市| 夏津县| 西和县| 盐边县| 县级市| 全南县| 祁门县| 红安县| 康平县| 三原县| 开原市| 镇宁| 苏尼特左旗| 孙吴县| 阿勒泰市| 黎川县| 阿克| 宿松县| 南昌市| 陕西省| 诏安县| 洛扎县| 九江县| 鹤岗市| 广东省| 五指山市| 华阴市| 庄浪县| 甘孜| 邵东县| 宜兰市| 通山县| 高尔夫| 山丹县| 乌恰县| 招远市| 剑阁县| 双辽市| 丽水市|