吴忠躺衫网络科技有限公司

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

GoF給裝飾者模式的定義

元閏子的邀請(qǐng) ? 來(lái)源:元閏子的邀請(qǐng) ? 作者:元閏子的邀請(qǐng) ? 2022-06-29 10:22 ? 次閱讀

上一篇:【Go實(shí)現(xiàn)】實(shí)踐GoF的23種設(shè)計(jì)模式:原型模式

簡(jiǎn)單的分布式應(yīng)用系統(tǒng)(示例代碼工程):https://github.com/ruanrunxue/Practice-Design-Pattern--Go-Implementation

簡(jiǎn)介

我們經(jīng)常會(huì)遇到“給現(xiàn)有對(duì)象/模塊新增功能”的場(chǎng)景,比如 http router 的開(kāi)發(fā)場(chǎng)景下,除了最基礎(chǔ)的路由功能之外,我們常常還會(huì)加上如日志、鑒權(quán)、流控等 middleware。如果你查看框架的源碼,就會(huì)發(fā)現(xiàn) middleware 功能的實(shí)現(xiàn)用的就是裝飾者模式(Decorator Pattern)。

GoF給裝飾者模式的定義如下:

Decorators provide a flexible alternative to subclassing for extending functionality. Attach additional responsibilities to an object dynamically.

簡(jiǎn)單來(lái)說(shuō),裝飾者模式通過(guò)組合的方式,提供了能夠動(dòng)態(tài)地給對(duì)象/模塊擴(kuò)展新功能的能力。理論上,只要沒(méi)有限制,它可以一直把功能疊加下去,具有很高的靈活性。

如果寫(xiě)過(guò) Java,那么一定對(duì) I/O Stream 體系不陌生,它是裝飾者模式的經(jīng)典用法,客戶端程序可以動(dòng)態(tài)地為原始的輸入輸出流添加功能,比如按字符串輸入輸出,加入緩沖等,使得整個(gè) I/O Stream 體系具有很高的可擴(kuò)展性和靈活性。

UML 結(jié)構(gòu)

0c30719e-f700-11ec-ba43-dac502259ad0.jpg

場(chǎng)景上下文

在簡(jiǎn)單的分布式應(yīng)用系統(tǒng)(示例代碼工程)中,我們?cè)O(shè)計(jì)了 Sidecar 邊車模塊,它的用處主要是為了 1)方便擴(kuò)展network.Socket的功能,如增加日志、流控等非業(yè)務(wù)功能;2)讓這些附加功能對(duì)業(yè)務(wù)程序隱藏起來(lái),也即業(yè)務(wù)程序只須關(guān)心看到network.Socket接口即可。

0c4d81d0-f700-11ec-ba43-dac502259ad0.jpg

代碼實(shí)現(xiàn)

Sidecar 的這個(gè)功能場(chǎng)景,很適合使用裝飾者模式來(lái)實(shí)現(xiàn),代碼如下:

//demo/network/socket.go
packagenetwork

//關(guān)鍵點(diǎn)1:定義被裝飾的抽象接口
//Socket網(wǎng)絡(luò)通信Socket接口
typeSocketinterface{
//Listen在endpoint指向地址上起監(jiān)聽(tīng)
Listen(endpointEndpoint)error
//Close關(guān)閉監(jiān)聽(tīng)
Close(endpointEndpoint)
//Send發(fā)送網(wǎng)絡(luò)報(bào)文
Send(packet*Packet)error
//Receive接收網(wǎng)絡(luò)報(bào)文
Receive(packet*Packet)
//AddListener增加網(wǎng)絡(luò)報(bào)文監(jiān)聽(tīng)者
AddListener(listenerSocketListener)
}

//關(guān)鍵點(diǎn)2:提供一個(gè)默認(rèn)的基礎(chǔ)實(shí)現(xiàn)
typesocketImplstruct{
listenerSocketListener
}

funcDefaultSocket()*socketImpl{
return&socketImpl{}
}

func(s*socketImpl)Listen(endpointEndpoint)error{
returnInstance().Listen(endpoint,s)
}
...//socketImpl的其他Socket實(shí)現(xiàn)方法


//demo/sidecar/flowctrl_sidecar.go
packagesidecar

//關(guān)鍵點(diǎn)3:定義裝飾器,實(shí)現(xiàn)被裝飾的接口
//FlowCtrlSidecarHTTP接收端流控功能裝飾器,自動(dòng)攔截Socket接收?qǐng)?bào)文,實(shí)現(xiàn)流控功能
typeFlowCtrlSidecarstruct{
//關(guān)鍵點(diǎn)4:裝飾器持有被裝飾的抽象接口作為成員屬性
socketnetwork.Socket
ctx*flowctrl.Context
}

//關(guān)鍵點(diǎn)5:對(duì)于需要擴(kuò)展功能的方法,新增擴(kuò)展功能
func(f*FlowCtrlSidecar)Receive(packet*network.Packet){
httpReq,ok:=packet.Payload().(*http.Request)
//如果不是HTTP請(qǐng)求,則不做流控處理
if!ok{
f.socket.Receive(packet)
return
}
//流控后返回429TooManyRequest響應(yīng)
if!f.ctx.TryAccept(){
httpResp:=http.ResponseOfId(httpReq.ReqId()).
AddStatusCode(http.StatusTooManyRequest).
AddProblemDetails("enterflowctrlstate")
f.socket.Send(network.NewPacket(packet.Dest(),packet.Src(),httpResp))
return
}
f.socket.Receive(packet)
}

//關(guān)鍵點(diǎn)6:不需要擴(kuò)展功能的方法,直接調(diào)用被裝飾接口的原生方法即可
func(f*FlowCtrlSidecar)Close(endpointnetwork.Endpoint){
f.socket.Close(endpoint)
}
...//FlowCtrlSidecar的其他方法

//關(guān)鍵點(diǎn)7:定義裝飾器的工廠方法,入?yún)楸谎b飾接口
funcNewFlowCtrlSidecar(socketnetwork.Socket)*FlowCtrlSidecar{
return&FlowCtrlSidecar{
socket:socket,
ctx:flowctrl.NewContext(),
}
}

//demo/sidecar/all_in_one_sidecar_factory.go
//關(guān)鍵點(diǎn)8:使用時(shí),通過(guò)裝飾器的工廠方法,把所有裝飾器和被裝飾者串聯(lián)起來(lái)
func(aAllInOneFactory)Create()network.Socket{
returnNewAccessLogSidecar(NewFlowCtrlSidecar(network.DefaultSocket()),a.producer)
}

總結(jié)實(shí)現(xiàn)裝飾者模式的幾個(gè)關(guān)鍵點(diǎn):

  1. 定義需要被裝飾的抽象接口,后續(xù)的裝飾器都是基于該接口進(jìn)行擴(kuò)展。
  2. 為抽象接口提供一個(gè)基礎(chǔ)實(shí)現(xiàn)。
  3. 定義裝飾器,并實(shí)現(xiàn)被裝飾的抽象接口。
  4. 裝飾器持有被裝飾的抽象接口作為成員屬性。“裝飾”的意思是在原有功能的基礎(chǔ)上擴(kuò)展新功能,因此必須持有原有功能的抽象接口。
  5. 在裝飾器中,對(duì)于需要擴(kuò)展功能的方法,新增擴(kuò)展功能。
  6. 不需要擴(kuò)展功能的方法,直接調(diào)用被裝飾接口的原生方法即可
  7. 為裝飾器定義一個(gè)工廠方法,入?yún)楸谎b飾接口。
  8. 使用時(shí),通過(guò)裝飾器的工廠方法,把所有裝飾器和被裝飾者串聯(lián)起來(lái)。

擴(kuò)展

Go 風(fēng)格的實(shí)現(xiàn)

在 Sidecar 的場(chǎng)景上下文中,被裝飾的Socket是一個(gè)相對(duì)復(fù)雜的接口,裝飾器通過(guò)實(shí)現(xiàn)Socket接口來(lái)進(jìn)行功能擴(kuò)展,是典型的面向?qū)ο箫L(fēng)格。

如果被裝飾者是一個(gè)簡(jiǎn)單的接口/方法/函數(shù),我們可以用更具 Go 風(fēng)格的實(shí)現(xiàn)方式,考慮前文提到的 http router 場(chǎng)景。如果你使用原生的net/http進(jìn)行 http router 開(kāi)發(fā),通常會(huì)這么實(shí)現(xiàn):

funcmain(){
//注冊(cè)/hello的router
http.HandleFunc("/hello",hello)
//啟動(dòng)http服務(wù)器
http.ListenAndServe("localhost:8080",nil)
}

//具體的請(qǐng)求處理邏輯,類型是http.HandlerFunc
funchello(whttp.ResponseWriter,r*http.Request){
w.Write([]byte("hello,world"))
}

其中,我們通過(guò)http.HandleFunc來(lái)注冊(cè)具體的 router,hello是具體的請(qǐng)求處理方法。現(xiàn)在,我們想為該 http 服務(wù)器增加日志、鑒權(quán)等通用功能,那么可以把func(w http.ResponseWriter, r *http.Request)作為被裝飾的抽象接口,通過(guò)新增日志、鑒權(quán)等裝飾器完成功能擴(kuò)展。

//demo/network/http/http_handle_func_decorator.go

//關(guān)鍵點(diǎn)1:確定被裝飾接口,這里為原生的http.HandlerFunc
typeHandlerFuncfunc(ResponseWriter,*Request)

//關(guān)鍵點(diǎn)2:定義裝飾器類型,是一個(gè)函數(shù)類型,入?yún)⒑头祷刂刀际莌ttp.HandlerFunc函數(shù)
typeHttpHandlerFuncDecoratorfunc(http.HandlerFunc)http.HandlerFunc

//關(guān)鍵點(diǎn)3:定義裝飾函數(shù),入?yún)楸谎b飾的接口和裝飾器可變列表
funcDecorate(hhttp.HandlerFunc,decorators...HttpHandlerFuncDecorator)http.HandlerFunc{
//關(guān)鍵點(diǎn)4:通過(guò)for循環(huán)遍歷裝飾器,完成對(duì)被裝飾接口的裝飾
for_,decorator:=rangedecorators{
h=decorator(h)
}
returnh
}

//關(guān)鍵點(diǎn)5:實(shí)現(xiàn)具體的裝飾器
funcWithBasicAuth(hhttp.HandlerFunc)http.HandlerFunc{
returnfunc(whttp.ResponseWriter,r*http.Request){
cookie,err:=r.Cookie("Auth")
iferr!=nil||cookie.Value!="Pass"{
w.WriteHeader(http.StatusForbidden)
return
}
//關(guān)鍵點(diǎn)6:完成功能擴(kuò)展之后,調(diào)用被裝飾的方法,才能將所有裝飾器和被裝飾者串起來(lái)
h(w,r)
}
}

funcWithLogger(hhttp.HandlerFunc)http.HandlerFunc{
returnfunc(whttp.ResponseWriter,r*http.Request){
log.Println(r.Form)
log.Printf("path%s",r.URL.Path)
h(w,r)
}
}

funchello(whttp.ResponseWriter,r*http.Request){
w.Write([]byte("hello,world"))
}

funcmain(){
//關(guān)鍵點(diǎn)7:通過(guò)Decorate函數(shù)完成對(duì)hello的裝飾
http.HandleFunc("/hello",Decorate(hello,WithLogger,WithBasicAuth))
//啟動(dòng)http服務(wù)器
http.ListenAndServe("localhost:8080",nil)
}

上述的裝飾者模式的實(shí)現(xiàn),用到了類似于Functional Options的技巧,也是巧妙利用了 Go 的函數(shù)式編程的特點(diǎn),總結(jié)下來(lái)有如下幾個(gè)關(guān)鍵點(diǎn):

  1. 確定被裝飾的接口,上述例子為http.HandlerFunc
  2. 定義裝飾器類型,是一個(gè)函數(shù)類型,入?yún)⒑头祷刂刀际潜谎b飾接口,上述例子為func(http.HandlerFunc) http.HandlerFunc
  3. 定義裝飾函數(shù),入?yún)楸谎b飾的接口和裝飾器可變列表,上述例子為Decorate方法。
  4. 在裝飾方法中,通過(guò)for循環(huán)遍歷裝飾器,完成對(duì)被裝飾接口的裝飾。這里是用來(lái)類似Functional Options的技巧,一定要注意裝飾器的順序
  5. 實(shí)現(xiàn)具體的裝飾器,上述例子為WithBasicAuthWithLogger函數(shù)。
  6. 在裝飾器中,完成功能擴(kuò)展之后,記得調(diào)用被裝飾者的接口,這樣才能將所有裝飾器和被裝飾者串起來(lái)。
  7. 在使用時(shí),通過(guò)裝飾函數(shù)完成對(duì)被裝飾者的裝飾,上述例子為Decorate(hello, WithLogger, WithBasicAuth)

Go 標(biāo)準(zhǔn)庫(kù)中的裝飾者模式

在 Go 標(biāo)準(zhǔn)庫(kù)中,也有一個(gè)運(yùn)用了裝飾者模式的模塊,就是context,其中關(guān)鍵的接口如下:

packagecontext

//被裝飾接口
typeContextinterface{
Deadline()(deadlinetime.Time,okbool)
Done()<-chanstruct{}
Err()error
Value(keyany)any
}

//cancel裝飾器
typecancelCtxstruct{
Context//被裝飾接口
musync.Mutex
doneatomic.Value
childrenmap[canceler]struct{}=
errerror
}
//cancel裝飾器的工廠方法
funcWithCancel(parentContext)(ctxContext,cancelCancelFunc){
//...
c:=newCancelCtx(parent)
propagateCancel(parent,&c)
return&c,func(){c.cancel(true,Canceled)}
}

//timer裝飾器
typetimerCtxstruct{
cancelCtx//被裝飾接口
timer*time.Timer

deadlinetime.Time
}
//timer裝飾器的工廠方法
funcWithDeadline(parentContext,dtime.Time)(Context,CancelFunc){
//...
c:=&timerCtx{
cancelCtx:newCancelCtx(parent),
deadline:d,
}
//...
returnc,func(){c.cancel(true,Canceled)}
}
//timer裝飾器的工廠方法
funcWithTimeout(parentContext,timeouttime.Duration)(Context,CancelFunc){
returnWithDeadline(parent,time.Now().Add(timeout))
}

//value裝飾器
typevalueCtxstruct{
Context//被裝飾接口
key,valany
}
//value裝飾器的工廠方法
funcWithValue(parentContext,key,valany)Context{
ifparent==nil{
panic("cannotcreatecontextfromnilparent")
}
//...
return&valueCtx{parent,key,val}
}
0c708ad6-f700-11ec-ba43-dac502259ad0.jpg

使用時(shí),可以這樣:

//使用時(shí),可以這樣
funcmain(){
ctx:=context.Background()
ctx=context.WithValue(ctx,"key1","value1")
ctx,_=context.WithTimeout(ctx,time.Duration(1))
ctx=context.WithValue(ctx,"key2","value2")
}

不管是 UML 結(jié)構(gòu),還是使用方法,context模塊都與傳統(tǒng)的裝飾者模式有一定出入,但也不妨礙context是裝飾者模式的典型運(yùn)用。還是那句話,學(xué)習(xí)設(shè)計(jì)模式,不能只記住它的結(jié)構(gòu),而是學(xué)習(xí)其中的動(dòng)機(jī)和原理

典型使用場(chǎng)景

  • I/O 流,比如為原始的 I/O 流增加緩沖、壓縮等功能。
  • Http Router,比如為基礎(chǔ)的 Http Router 能力增加日志、鑒權(quán)、Cookie等功能。
  • ......

優(yōu)缺點(diǎn)

優(yōu)點(diǎn)

  1. 遵循開(kāi)閉原則,能夠在不修改老代碼的情況下擴(kuò)展新功能。
  2. 可以用多個(gè)裝飾器把多個(gè)功能組合起來(lái),理論上可以無(wú)限組合。

缺點(diǎn)

  1. 一定要注意裝飾器裝飾的順序,否則容易出現(xiàn)不在預(yù)期內(nèi)的行為。
  2. 當(dāng)裝飾器越來(lái)越多之后,系統(tǒng)也會(huì)變得復(fù)雜。

與其他模式的關(guān)聯(lián)

裝飾者模式和代理模式具有很高的相似性,但是兩種所強(qiáng)調(diào)的點(diǎn)不一樣。前者強(qiáng)調(diào)的是為本體對(duì)象添加新的功能;后者強(qiáng)調(diào)的是對(duì)本體對(duì)象的訪問(wèn)控制

裝飾者模式和適配器模式的區(qū)別是,前者只會(huì)擴(kuò)展功能而不會(huì)修改接口;后者則會(huì)修改接口。

文章配圖

可以在用Keynote畫(huà)出手繪風(fēng)格的配圖中找到文章的繪圖方法。

審核編輯 :李倩


聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 模塊
    +關(guān)注

    關(guān)注

    7

    文章

    2735

    瀏覽量

    47754
  • UML
    UML
    +關(guān)注

    關(guān)注

    0

    文章

    122

    瀏覽量

    30903

原文標(biāo)題:【Go實(shí)現(xiàn)】實(shí)踐GoF的23種設(shè)計(jì)模式:裝飾者模式

文章出處:【微信號(hào):yuanrunzi,微信公眾號(hào):元閏子的邀請(qǐng)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    AN25-開(kāi)關(guān)穩(wěn)壓器:恐懼的溫柔指南

    電子發(fā)燒友網(wǎng)站提供《AN25-開(kāi)關(guān)穩(wěn)壓器:恐懼的溫柔指南.pdf》資料免費(fèi)下載
    發(fā)表于 01-09 14:07 ?0次下載
    AN25-開(kāi)關(guān)穩(wěn)壓器:<b class='flag-5'>給</b>恐懼<b class='flag-5'>者</b>的溫柔指南

    設(shè)計(jì)模式-策略模式

    作者:京東工業(yè) 孫磊 一、概念 策略模式(Strategy Pattern)也稱為(Policy Parttern)。 它定義了算法家族,分別封裝起來(lái),讓它們之間可以互相替換,此模式讓算法的變換
    的頭像 發(fā)表于 01-08 13:47 ?103次閱讀
    設(shè)計(jì)<b class='flag-5'>模式</b>-策略<b class='flag-5'>模式</b>

    給我兩分鐘,搞懂發(fā)布-訂閱模式很輕松!

    什么是發(fā)布/訂閱模式?舉一個(gè)生活中常見(jiàn)的例子說(shuō)明:小李到某房產(chǎn)中介提出租房需求,根據(jù)需求,房產(chǎn)中介將之前房東發(fā)布的出租信息提供給小李選擇,小李確定租房后,中介會(huì)將信息同步房東知曉。這是一個(gè)典型
    的頭像 發(fā)表于 10-25 08:06 ?490次閱讀
    給我兩分鐘,搞懂發(fā)布-訂閱<b class='flag-5'>模式</b>很輕松!

    usb主機(jī)模式和設(shè)備模式的區(qū)別

    USB(通用串行總線)是一種廣泛使用的接口技術(shù),用于連接計(jì)算機(jī)和外部設(shè)備。USB主機(jī)模式和設(shè)備模式是USB通信中的兩種不同角色,它們定義了設(shè)備和計(jì)算機(jī)之間的通信方式。以下是對(duì)這兩種模式
    的頭像 發(fā)表于 09-25 09:06 ?1116次閱讀

    【每天學(xué)點(diǎn)AI】一個(gè)例子帶你了解Python裝飾器到底在干嘛!

    今天我們來(lái)聊聊一種能給你的代碼變得“加料”的神器——Python裝飾器。就像一杯咖啡,原本它是苦的,為了讓它符合我的口味,我給它添加了糖,添加之后就完美的符合了我的口味。那么,裝飾器又是如何代碼
    的頭像 發(fā)表于 09-20 16:54 ?596次閱讀
    【每天學(xué)點(diǎn)AI】一個(gè)例子帶你了解Python<b class='flag-5'>裝飾</b>器到底在干嘛!

    DMX512AW裝飾照明驅(qū)動(dòng)IC規(guī)格書(shū)

    電子發(fā)燒友網(wǎng)站提供《DMX512AW裝飾照明驅(qū)動(dòng)IC規(guī)格書(shū).pdf》資料免費(fèi)下載
    發(fā)表于 07-09 16:52 ?0次下載

    DMX512P-W裝飾照明驅(qū)動(dòng)IC產(chǎn)品說(shuō)明書(shū)

    電子發(fā)燒友網(wǎng)站提供《DMX512P-W裝飾照明驅(qū)動(dòng)IC產(chǎn)品說(shuō)明書(shū).pdf》資料免費(fèi)下載
    發(fā)表于 07-09 16:51 ?5次下載

    HarmonyOS實(shí)戰(zhàn)開(kāi)發(fā)-深度探索與打造個(gè)性化自定義組件

    ,容器組件,媒體組件,繪制組件,畫(huà)布組件組件等,如Button、Text 是基礎(chǔ)組件。 由開(kāi)發(fā)在基礎(chǔ)組件基礎(chǔ)上 添加一些封裝和修飾 定義的組件稱為自定義組件。自定義組件的實(shí)現(xiàn)大大提高
    發(fā)表于 05-08 16:30

    實(shí)踐GoF的23種設(shè)計(jì)模式實(shí)現(xiàn):橋接模式

    也即,將抽象部分和實(shí)現(xiàn)部分進(jìn)行解耦,使得它們能夠各自往獨(dú)立的方向變化。
    的頭像 發(fā)表于 04-14 09:30 ?520次閱讀
    實(shí)踐<b class='flag-5'>GoF</b>的23種設(shè)計(jì)<b class='flag-5'>模式</b>實(shí)現(xiàn):橋接<b class='flag-5'>模式</b>

    鴻蒙OS開(kāi)發(fā)實(shí)例:【ArkTS類庫(kù)多線程@Concurrent裝飾器校驗(yàn)并發(fā)函數(shù)】

    在使用TaskPool時(shí),執(zhí)行的并發(fā)函數(shù)需要使用該裝飾器修飾,否則無(wú)法通過(guò)相關(guān)校驗(yàn)。從API version 9開(kāi)始,該裝飾器支持在ArkTS卡片中使用。
    的頭像 發(fā)表于 04-02 14:45 ?788次閱讀
    鴻蒙OS開(kāi)發(fā)實(shí)例:【ArkTS類庫(kù)多線程@Concurrent<b class='flag-5'>裝飾</b>器校驗(yàn)并發(fā)函數(shù)】

    實(shí)踐GoF的23種設(shè)計(jì)模式:解釋器模式

    解釋器模式(Interpreter Pattern)應(yīng)該是 GoF 的 23 種設(shè)計(jì)模式中使用頻率最少的一種了,它的應(yīng)用場(chǎng)景較為局限。
    的頭像 發(fā)表于 04-01 11:01 ?766次閱讀
    實(shí)踐<b class='flag-5'>GoF</b>的23種設(shè)計(jì)<b class='flag-5'>模式</b>:解釋器<b class='flag-5'>模式</b>

    LoRa模組FSK模式下WOR功耗估算實(shí)例

    的LoRa模式,而是使用的該模組的FSK模式,并需要使用FSK模式下的WOR功能。在確定使用FSK模式下的WOR功能時(shí)需要先估算功耗是否能滿足使用
    的頭像 發(fā)表于 03-29 08:12 ?5784次閱讀
    LoRa模組FSK<b class='flag-5'>模式</b>下WOR功耗估算實(shí)例

    鴻蒙OS開(kāi)發(fā)實(shí)例:【裝飾器@Observed@ObjectLink】

    加深對(duì)@Observed@ObjectLink 裝飾器使用的理解,以小故事做注釋
    的頭像 發(fā)表于 03-28 17:05 ?1057次閱讀
    鴻蒙OS開(kāi)發(fā)實(shí)例:【<b class='flag-5'>裝飾</b>器@Observed@ObjectLink】

    鴻蒙原生應(yīng)用開(kāi)發(fā)-ArkTS語(yǔ)言基礎(chǔ)類庫(kù)多線程@Concurrent裝飾器校驗(yàn)并發(fā)函數(shù)

    在使用TaskPool時(shí),執(zhí)行的并發(fā)函數(shù)需要使用該裝飾器修飾,否則無(wú)法通過(guò)相關(guān)校驗(yàn)。從API version 9開(kāi)始,該裝飾器支持在ArkTS卡片中使用。 裝飾器說(shuō)明 裝飾器使用示例
    發(fā)表于 03-18 10:30

    ?用于LED裝飾照明DMX512并聯(lián)驅(qū)動(dòng)控制芯片作用與應(yīng)用領(lǐng)域

    LED裝飾照明DMX512并聯(lián)驅(qū)動(dòng)控制芯片是一種新型的照明控制芯片,它能夠?qū)崿F(xiàn)LED燈的分段控制,提供更加豐富多彩的照明效果。在現(xiàn)代建筑裝飾和舞臺(tái)演出中,LED裝飾照明已經(jīng)成為主流,而DMX512
    的頭像 發(fā)表于 02-23 16:40 ?770次閱讀
    ?用于LED<b class='flag-5'>裝飾</b>照明DMX512并聯(lián)驅(qū)動(dòng)控制芯片作用與應(yīng)用領(lǐng)域
    商水县| 大发888游戏平台 新葡京| 天堂鸟百家乐官网的玩法技巧和规则| 万源市| 大发888下载安装| 百家乐网上赌博网| 百家乐官网赢退输进有哪些| 普洱| 真人游戏豆瓣| 百家乐园小区户型图| 百家乐官网楼梯缆| 贵族娱乐城信誉| 威尼斯人娱乐城好吗| 百家乐游戏真钱游戏| 百家乐官网客户端下载| 娱乐城送18元体验金| 网上百家乐公| 百家乐平台导航| 回力百家乐官网的玩法技巧和规则| 百家乐官网稳定打法| 大发888国际赌场娱乐网规则| 百家乐皇室百家乐| 百家乐投资心得| 百家乐官网博赌场| 百家乐官网真人视屏游戏| 88娱乐城天上人间| 大发888登录| 庞博百家乐的玩法技巧和规则| 百家乐分析博彩正网| 法拉利百家乐官网的玩法技巧和规则| 玩百家乐官网是否有技巧| 甘肃省| 娱乐城官网| 威尼斯人娱乐场安全吗| 百家乐论坛香港马会| 百家乐实战技术| 澳门百家乐官网网址多少| 博彩排名| 顶级赌场 足彩分析| 大发888娱乐大发体育| 澳门百家乐游戏官网|