成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

程序里對(duì)象很深很大,可以用這個(gè)設(shè)計(jì)模式緩解一下

開(kāi)發(fā) 前端
在項(xiàng)目中使用原型模式時(shí),可能需要在項(xiàng)目初始化時(shí)就把提供克隆能力的原型對(duì)象創(chuàng)建好,在多線程環(huán)境下,每個(gè)線程處理任務(wù)的時(shí)候,用到了相關(guān)對(duì)象,可以去原型對(duì)象那里拷貝。

如果一個(gè)類(lèi)的有非常多的屬性,層級(jí)還很深。這個(gè)妥妥的是我的對(duì)象很大,你創(chuàng)建的時(shí)候忍一下......那你每次要?jiǎng)?chuàng)建的時(shí)候都忍一下?有沒(méi)有一種好的方式讓我們創(chuàng)建太的時(shí)候使用體驗(yàn)更好一點(diǎn)呢? 今天的文章里就給大家介紹一種設(shè)計(jì)模式,來(lái)解決這個(gè)問(wèn)題。

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

什么是原型模式

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

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

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

type Prototype interface {
Clone() SpecificType
}

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

圖片

原型模式--UML類(lèi)圖

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

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

// 示例代碼來(lái)自: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ù)庫(kù)中獲取數(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)建對(duì)象所花費(fèi)的時(shí)間和資源消耗,提升性能。

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

使用場(chǎng)景

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

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

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

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

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

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

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

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

原型模式總結(jié)

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

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

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

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

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

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

責(zé)任編輯:武曉燕 來(lái)源: 網(wǎng)管叨bi叨
相關(guān)推薦

2021-12-27 18:00:30

對(duì)象數(shù)組Java

2022-11-16 08:58:33

Go模版模式策略模式

2023-02-06 08:54:59

Go設(shè)計(jì)模式項(xiàng)目

2011-01-21 13:56:44

SendmailSolaris

2021-10-09 18:26:59

二叉樹(shù)多叉樹(shù)搜索

2021-12-27 08:45:19

固態(tài)硬盤(pán)硬盤(pán)存儲(chǔ)

2021-06-10 06:57:39

JS 操作符號(hào)

2021-05-31 06:28:35

AutoMapper對(duì)象映射器

2022-03-07 06:34:22

CQRS數(shù)據(jù)庫(kù)數(shù)據(jù)模型

2021-02-07 10:34:21

可視化編程Numpy

2022-04-26 05:57:18

微服務(wù)Nacos

2021-01-28 10:23:26

Seata模式分布式

2022-02-24 17:37:47

低代碼拖拽前端

2021-11-16 12:25:14

jsPPT前端

2016-12-06 12:48:32

開(kāi)源設(shè)計(jì)

2022-10-30 17:32:25

設(shè)計(jì)模式單例模式

2018-08-31 14:43:31

病毒手機(jī)自查

2019-06-17 05:00:53

預(yù)測(cè)性維護(hù)物聯(lián)網(wǎng)IOT

2020-10-20 14:12:54

B站開(kāi)源彈幕

2022-03-10 07:39:33

.NET部署模式
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 国产美女h视频 | 羞羞的视频免费在线观看 | 天堂一区二区三区 | 国产精品电影网 | 一级a爱片久久毛片 | 精品国产一区二区三区在线观看 | 欧美精品黄 | 国产高清视频在线观看 | 精品国产一区二区三区久久久四川 | 99精品一区二区 | 久久这里只有精品首页 | 欧美视频1 | 欧美日韩国产三级 | 性网站免费 | 亚洲免费久久久 | 手机在线一区二区三区 | 99精品欧美一区二区蜜桃免费 | 欧美精品一区在线 | 精品国产乱码久久久久久88av | 欧美激情久久久 | 日韩欧美三区 | 国产精品欧美一区二区三区不卡 | 免费在线观看毛片 | 亚洲天堂成人在线视频 | 在线成人免费视频 | 国产欧美在线观看 | 日韩在线观看中文字幕 | 成人亚洲在线 | 日韩欧美在线视频播放 | 伊人伊人 | 日本精品一区二区三区在线观看视频 | 最新日韩在线 | 天天拍天天操 | 欧美a在线| 国产成人免费视频网站视频社区 | 日本高清视频网站 | 99re在线视频免费观看 | 国内精品视频在线 | 激情久久久久 | 国产精品影视在线观看 | 亚洲欧美国产毛片在线 |