大话设计模式 Golang 版 - 装饰模式

原文链接:大话设计模式 Golang 版 - 装饰模式

关于

大话设计模式 Golang 版 是将 <<大话设计模式【Java溢彩加强版】(作者:程杰)>> 里面的 Java 代码用 Golang 重新写了一遍, 然后结合 图说设计模式 做总结归纳

简述

装饰模式(Decorator Pattern) :动态地给一个对象增加一些额外的职责(Responsibility),就增加对象功能来说,装饰模式比生成子类实现更为灵活。其别名也可以称为包装器(Wrapper),与适配器模式的别名相同,但它们适用于不同的场合。根据翻译的不同,装饰模式也有人称之为“油漆工模式”,它是一种对象结构型模式。

UML 结构

下面的 UML 图是原书中使用 Java 的 UML 图, 由于 Golang 中没有抽象类, 所以在代码实现时需要将 Java 中的抽象类转换为接口来实现

在这里插入图片描述

  • Decorator 和 Component 是一种聚合关系(aggregation),用一条带空心菱形箭头的直线表示;

聚合关系(aggregation)
聚合关系用一条带空心菱形箭头的直线表示,如上图表示 Component 聚合到 Decorator 上,或者说 Decorator 由 Component 组成;

聚合关系用于表示实体对象之间的关系,表示整体由部分构成的语义, 表示一种弱的 "拥有"关系, 体现的是A对象可以包含B对象, 但是B对象不是A对象的一部分;例如一个部门由多个员工组成;

与组合关系不同的是,整体和部分不是强依赖的,即使整体不存在了,部分仍然存在;例如, 部门撤销了,人员不会消失,他们依然存在;

代码实现

源码下载地址: github.com/chapter06/

由于 Golang 中没有抽象类, 实现方式上和 Java 有些不同:

Component 是个接口类型

type Component interface {
	Operation()
}

type ConcreteComponent struct {
}

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

Decorator 也是个接口类型, 然后将 Component 嵌入到 Decorator. 注意 DecoratorCommon 的使用, 我们可以将具体装饰器 (ConcreteDecoratorA )共同的部分提取到这个结构体中, 然后在具体装饰器中嵌入 DecoratorCommon 结构体, 这样的实现就类似于 Java 中的抽象类.

type Decorator interface {
	Component
	SetComponent()
}

type DecoratorCommon struct {
	component Component
}

func (c *DecoratorCommon) SetComponent(component Component) {
	c.component = component
}

func (c *DecoratorCommon) Operation() {
	if c.component != nil {
		c.component.Operation()
	} else {
		fmt.Println("component is nil")
	}
}

type ConcreteDecoratorA struct {
	DecoratorCommon
	addedState string
}

func (c *ConcreteDecoratorA) Operation() {
	c.DecoratorCommon.Operation()

	c.addedState = "具体装饰对象 A 的独有操作"
	fmt.Println(c.addedState)
}

典型应用场景

在以下情况下可以使用策略模式:

  • 在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。
  • 需要动态地给一个对象增加功能,这些功能也可以动态地被撤销。

优缺点

优点

  • 把类中的装饰功能从类中搬移去除,这样可以简化原有的类。有效地把类的核心职责和装饰功能区分开了。而且可以去除相关类中重复的装饰逻辑。
  • 通过使用不同的具体装饰类以及这些装饰类的排列组合,可以创造出很多不同行为的组合。可以使用多个具体装饰类来装饰同一对象,得到功能更为强大的对象。
  • 具体构件类与具体装饰类可以独立变化,用户可以根据需要增加新的具体构件类和具体装饰类,在使用时再对其进行组合,原有代码无须改变,符合“开闭原则”

缺点

  • 使用装饰模式进行系统设计时将产生很多小对象,这些对象的区别在于它们之间相互连接的方式有所不同,而不是它们的类或者属性值有所不同,同时还将产生很多具体装饰类。这些装饰类和小对象的产生将增加系统的复杂度,加大学习与理解的难度。
  • 这种比继承更加灵活机动的特性,也同时意味着装饰模式比继承更加易于出错,排错也很困难,对于多次装饰的对象,调试时寻找错误可能需要逐级排查,较为烦琐。

参考链接

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值