Golang设计模式——22装饰者模式

装饰者模式

优点

  1. 是指在不改变原有对象的基础之上,将功能附加到对象上.提供了比继承更灵活的替代方法,属于结构型模式
  2. 动态的给一个对象增加一些额外的职责,就增加功能来说,装饰模式相比生产子类更为灵活

缺点

  1. 使用装饰模式进行系统设计时将产生很多小对象,这些对象的区别在于它们之间相互连接的方式有所不同,而不是它们的类或者属性值有所不同,大量小对象的产生势必会占用更多的系统资源,在一定程序上影响程序的性能。
  2. 装饰模式提供了一种比继承更加灵活机动的解决方案,但同时也意味着比继承更加易于出错,排错也很困难,对于多次装饰的对象,调试时寻找错误可能需要逐级排查,较为繁琐。

场景

  1. 用于拓展一个类的功能或者给一个类添加附加职责
  2. 动态的给一个对象添加功能,这些功能可以再动态的撤销。
  3. 需要为一批的兄弟类进行改装或加装功能。

代码

在这里插入图片描述

package Decorator

import "fmt"

type Component interface {
	Operation()
}
type ConcreteComponent struct {
}

func (c *ConcreteComponent) Operation() {
	fmt.Println("具体的对象开始操作...")
}

type Decorator struct {
	cc Component
}

func (d *Decorator) SetComponent(c Component) {
	d.cc = c
}

func (d *Decorator) Operation() {
	if d.cc != nil {
		d.cc.Operation()
	}
}

type DecoratorA struct {
	Decorator
}

func (d *DecoratorA) Operation() {
	d.cc.Operation()
	d.IndependentMethod()
}
func (d *DecoratorA) IndependentMethod() {
	fmt.Println("装饰A扩展的方法")
}

type DecoratorB struct {
	Decorator
}

func (d *DecoratorB) Operation() {
	d.cc.Operation()
	fmt.Println(d.String())
}
func (d *DecoratorB) String() string {
	return "装饰B扩展的方法"
}

package Decorator

import "testing"

func TestDecorator_Operation(t *testing.T) {
	objectA := &ConcreteComponent{}
	cdA := &DecoratorA{}
	cdB := &DecoratorB{}
	cdA.SetComponent(objectA)
	cdB.SetComponent(cdA)
	cdB.Operation()
}

package Decorator

import (
	"log"
	"math"
	"time"
)

func pi(n int) float64 {
	ch := make(chan float64)
	for k := 0; k < n; k++ {
		go func(ch chan float64, k float64) {
			ch <- 4 * math.Pow(-1, k) / (2*k + 1)
		}(ch, float64(k))
	}
	result := 0.0
	for i := 0; i < n; i++ {
		result += <-ch
	}
	return result
}

type piFunc func(int) float64

func WrapLogger(fun piFunc, logger *log.Logger) piFunc {
	return func(n int) float64 {
		fn := func(n int) (result float64) {
			defer func(t time.Time) {
				logger.Printf("took=%v,n=%v,result=%v", time.Since(t), n, result)
			}(time.Now())
			return fun(n)
		}
		return fn(n)
	}
}

package Decorator

import (
	"log"
	"os"
	"testing"
)

func TestWrapLogger(t *testing.T) {
	f := WrapLogger(pi, log.New(os.Stdout, "test ", 1))
	f(100000)
}

其他设计模式

设计模式Git源代码
00简单工厂模式
01工厂方法模式
02抽象工厂模式
03外观模式
04建造者模式
05桥接模式
06命令模式
07迭代器模式
08模板模式
09访问者模式
10备忘录模式
11责任链模式
12中介模式
13原型模式
14状态模式
15策略模式
16享元模式
17组合模式
18解释器模式
19单例模式
20适配器模式
21代理模式
22装饰器模式
23观察者模式

posted @ 2021-09-26 15:12  cheems~  阅读(55)  评论(0编辑  收藏  举报