装饰器模式(Decorator Design Pattern)
装饰器模式允许向一个现有的对象添加新的功能,同时又不改变它的结构。装饰器模式创建了一个装饰类,用来包装原有的类,装饰器模式又被称为包装器模式(Wrapper)。
装饰器模式有4个角色:
- 抽象构件(Component): 被装饰对象的抽象。
- 具体构件(Concrete Component):实现抽象构件,是被装饰的对象。
- 抽象装饰器(Decorator): 关联抽象构件,可通过具体装饰器装饰具体构件。
- 具体装饰器(Concrete Decorator): 实现抽象装饰器的方法,并对具体构件进行装饰,即为具体构件对象添加新的职责。
示例代码
直接看上面的说明可能会比较模糊,游戏中的武器是很好的一个例子,看下代码:
package decorator
import "fmt"
//武器
type Weapon interface {
Attack() //攻击
}
//皮肤
type Skin interface {
Protect() //皮肤有不同的保护值
}
//枪
type Gun struct{}
func (g Gun) Attack() {
fmt.Println("手枪-射击")
}
//大炮
type Cannon struct{}
func (c Cannon) Attack() {
fmt.Println("加农大炮——开火")
}
//电玩小子皮肤
type GameBoySkin struct{}
func (g GameBoySkin) Protect() {
fmt.Println("穿上电玩小子批发武力值+10,保护+10")
}
//游戏角色
type Characters interface {
Weapon(Weapon)
Skin(Skin)
Attack()
}
//游戏角色-鲁班七号
type Luban struct {
skin Skin
weapon Weapon
}
func (l *Luban) Weapon(w Weapon) {
l.weapon = w
}
func (l *Luban) Skin(s Skin) {
l.skin = s
l.skin.Protect()
}
func (l Luban) Attack() {
l.weapon.Attack()
}
调用:
//武器
var gun Weapon = &Gun{}
var cannon Weapon = &Cannon{}
//皮肤
var gameBoySkin Skin = &GameBoySkin{}
//游戏角色
var luban Characters = &Luban{}
luban.Weapon(gun)
luban.Attack()
luban.Skin(gameBoySkin) //穿上皮肤
luban.Weapon(cannon) //使用加农大炮
luban.Attack() //攻击
// Output:
// 手枪-射击
// 穿上电玩小子批发武力值+10,保护+10
// 加农大炮——开火
装饰器模式和桥接模式区别
适配器模式是要将一个接口转变成另一个接口,它的目的是通过改变接口来达到重复使用的目的;
而装饰器模式不是要改变被装饰者对象的接口,而是恰恰要保持原有的接口,但是增强原有对象的功能,或者改变原有对象的处理方法而提升性能。比如上面例子中游戏角色通过改变武器达到不同的武力值,通过增加皮肤也可以增加武力和保护值。