【结构型模式】装饰器模式

文章目录

装饰器模式

装饰器模式(Decorator Pattern):动态地给一个对象增加一些额外的职责,对于"增加对象功能"而言,装饰器模式比生成子类实现更为灵活,且装饰器模式可以无限叠加。

装饰器模式当中的角色和职责

装饰器模式的标准类图如下:

  • Component(抽象构件):是具体构件和抽象装饰器的共同父类,声明了在具体构件中需要实现的业务方法。
  • ConcreteComponent(具体构件):是抽象构件的子嘞,用于定义具体的构件对象。装饰器可以为它添加额外的职责(方法)。

装饰器模式的代码实现

参考《Easy 搞定 Golang 设计模式》,下面以"添加手机配件"为场景,实现一个使用装饰器模式的 Demo:

go 复制代码
package main

import "fmt"

// --- --- --- 抽象层 --- --- ---
// 定义抽象的构件
type Phone interface {
	Show() // 构件的功能
}

// 装饰器基础类, 本应该定义为 interface, 但由于 Golang 的 interface 只有方法没有成员, 所以定义为 struct
type Decorator struct {
	phone Phone // 通过组合的方式实现 Decorator 基础类
}

func (d *Decorator) Show() {}

// --- --- --- 实现层 --- --- ---
// 定义具体的构件
type Apple struct{}

func (ap *Apple) Show() {
	fmt.Println("正在使用苹果手机...")
}

type Realme struct{}

func (rm *Realme) Show() {
	fmt.Println("正在使用真我手机...")
}

// 定义具体的装饰器
type TiemoDecorator struct {
	Decorator // 继承基础的装饰器类(主要继承 Phone 的成员属性)
}

func (td *TiemoDecorator) Show() {
	td.phone.Show() // 调用被装饰构件的原方法
	fmt.Println("贴膜的手机")
}

func NewTiemoDecorator(phone Phone) Phone {
	return &TiemoDecorator{Decorator{phone}}
}

type ShoujikeDecorator struct {
	Decorator
}

func (sd *ShoujikeDecorator) Show() {
	sd.phone.Show()
	fmt.Println("加装手机壳的手机")
}

func NewShoujikeDecorator(phone Phone) Phone {
	return &ShoujikeDecorator{Decorator{phone}}
}

func main() {
	var iphone Phone
	iphone = new(Apple)
	iphone.Show() // 调用原构件的方法

	var tiemoIPhone Phone
	tiemoIPhone = NewTiemoDecorator(iphone)
	tiemoIPhone.Show()

	var shoujikeIPhone Phone
	shoujikeIPhone = NewShoujikeDecorator(iphone)
	shoujikeIPhone.Show()

	var tiemoAndShoujikeIPhone Phone
	tiemoAndShoujikeIPhone = NewShoujikeDecorator(tiemoIPhone)
	tiemoAndShoujikeIPhone.Show()
}

装饰器模式与代理模式有何不同?

装饰器模式相较于代理模式而言,其动态性更好一些。可以根据不同的场景选择不同的模式,比如对于逻辑上需要增加的场景,可以使用代理模式;而对于需要无状态平行增加功能的场景,则可以选用装饰器模式,因为装饰器模式可以进行无状态的迭代。

装饰器模式的优缺点

优点

  1. 对于扩展一个对象的功能,装饰器模式比继承更加灵活,不会导致类的个数急剧增加;
  2. 可以通过一种动态的方式来扩展一个对象的功能,从而实现不同的行为;
  3. 可以对一个对象进行多次装饰(无状态地平行添加功能);
  4. 具体的构件类与具体的装饰器类可以独立变化,用户可以根据需要新增具体构件类和具体装饰器类,原有代码无需改变,符合"开闭原则"。

缺点

  1. 使用装饰器模式进行系统设计时会产生很多小的对象,大量小对象的产生势必会占用更多的系统资源,影响程序性能;
  2. 装饰器模式比继承更加灵活,但同时也意味着相较于继承,装饰器模式更容易出错。对于多次装饰的对象,如果出现问题,调试时需要逐级排查,较为繁琐。

适用场景

  1. 通过动态、透明的方式为单个对象添加职责;
  2. 当不能采用继承的方式对系统进行扩展或采用继承不利于系统扩展与维护时,可以使用装饰器模式。
相关推荐
Zane19941 天前
一个 new 就能创建对象,为什么还要拆出单例、工厂、建造者、原型四种模式?
设计模式
怕浪猫2 天前
一行命令复刻爆款视频,我把 Hypit 从安装跑到了出片
人工智能·设计模式·程序员
Zane19942 天前
函数式编程里的函数,其实不是你天天写的那个函数——三大编程范式的边界在哪
设计模式
Zane19943 天前
策略模式现在该不该上?一次讲清楚过度设计和设计不足怎么找平衡
设计模式
她说..3 天前
常见设计模式-模板方法模式
java·spring·设计模式·springboot
xiaofeiyang1504 天前
第六章 · 桥接 — 三支毛笔,画出九种颜色
设计模式
Shadow(⊙o⊙)4 天前
OTOL设计模式 One Thread One Loop
服务器·网络·设计模式
sarasuki5 天前
如何让LLM 能在半夜偷偷打开网易云呢?
人工智能·设计模式·agent
小王师傅665 天前
【设计模式】装饰模式(四):框架源码实战——从 Java I/O 到 Spring 到 MyBatis
java·设计模式
执明wa5 天前
Android RecyclerView 多类型, 多种 Item
android·xml·开发语言·设计模式·android studio