【Golang設計模式】2.裝飾器模式


2. 裝飾器模式

裝飾器模式,動態地給一個對象添加一些額外的職責,就增加功能來說,裝飾器模式比生成子類更加靈活。它把每個要裝飾的功能放在單獨的類中,並讓這個類包裝它所要裝飾的對象,在使用時要注意裝飾的順序。

比如我們想給核心代碼添加日志打印功能,但是又不能改動原有代碼,可以使用裝飾器模式來包裝原有的代碼。

在路徑decorator\下新建文件decorator.go,包名為decorator

package decorator

// ...

如下為工作代碼:

// 工作代碼
func Work() {
	fmt.Println("工作中...")
	time.Sleep(time.Second)
}

定義一個裝飾器函數來包裝工作代碼:

// logger函數包裝工作代碼
func Logger(f func()) {
	now := time.Now()
	fmt.Printf("開始:%v\n", now.Format("2006-01-02 15:04:05.000"))
	f() // 工作代碼
	end := time.Now()
	fmt.Printf("結束:%v\n", end.Format("2006-01-02 15:04:05.000"))
	fmt.Printf("耗時:%v\n", end.Sub(now))
}

加入工作代碼的函數簽名與Logger()函數的參數不匹配,這時候可以使用橋接模式定義一個橋接函數,來把2個函數橋接起來:

// 工作代碼——需要接受參數
func WorkWithArgs(name string) {
	fmt.Printf("%s——工作中...", name)
	time.Sleep(time.Second * 2)
}

// 工作方法與裝飾器不匹配,用中間方法進行橋接
func Bridge(f func(string), name string) func() {
	return func() {
		f(name)
	}
}

在路徑decorator的同級目錄下新建main.go用於測試方法:

package main

import (
	"fmt"
	"github.com/loveshes/go-design-patterns/pattern/decorator-pattern/decorator"
)

func main() {
	work := decorator.Work
	// 直接調用work()
	work()
	fmt.Println()

	// 使用裝飾器調用work()
	decorator.Logger(work)
	fmt.Println()

	// 橋接方法
	work2 := decorator.WorkWithArgs
	bridge := decorator.Bridge
	decorator.Logger(bridge(work2, "[工作方法]"))
}

輸出為

工作中...

開始:2020-04-19 23:08:36.317
工作中...
結束:2020-04-19 23:08:37.336
耗時:1.0190352s

開始:2020-04-19 23:08:37.336
[工作方法]——工作中...結束:2020-04-19 23:08:39.337
耗時:2.0000624s

完整示例


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM