装饰器模式
定义
装饰模式:动态的给一些对象添加额外的职责,就增加功能来说,装饰模式比生成子类更灵活。
举个栗子:
我们现在买手机或者电脑,都有基础配置,然后根据我们选择的运行内存的大小,具体的CPU,手机或电脑的价格最终价格就是不一样的。这里就用到装饰模式,定制的内存和CPU对我们的设备进行了装饰作用。
看下结构图
代码实现
// 基础款 16g运存 10代cpu
type basicPhone struct {
}
func (p *basicPhone) getPrice() int {
return 2000
}
// 32g运存
type choose32RAMPhone struct {
phone phone
}
func (r *choose32RAMPhone) getPrice() int {
price := r.phone.getPrice()
return price + 500
}
// 11代CPU
type choose11CPUPhone struct {
phone phone
}
func (r *choose11CPUPhone) getPrice() int {
price := r.phone.getPrice()
return price + 1000
}
测试代码
func TestDecorator(t *testing.T) {
phone := &basicPhone{}
choose32RAMPhone := &choose32RAMPhone{
phone: phone,
}
orderPhone := &choose11CPUPhone{
phone: choose32RAMPhone,
}
t.Log(orderPhone.getPrice())
}
优点
1、装饰器是继承的有力补充,比继承灵活,在不改变原有对象的情况下,动态的给一个对象扩展功能,即插即用
2、通过使用不用装饰类及这些装饰类的排列组合,可以实现不同效果
3、装饰器模式完全遵守开闭原则
装饰器模式主要解决继承关系过于复杂的问题,通过组合来替代继承。它主要的作用是给原始类添加增强功能。这也是判断是否该用装饰器模式的一个重要的依据。除此之外,装饰器模式还有一个特点,那就是可以对原始类嵌套使用多个装饰器。为了满足这个应用场景,在设计的时候,装饰器类需要跟原始类继承相同的抽象类或者接口。
缺点
装饰器模式会增加许多子类,过度使用会增加程序得复杂性。
适用范围
1、扩展一个类的功能。
2、动态增加功能,动态撤销。
装饰器模式和桥接模式的区别
两个模式都是为了解决子类过多问题, 但他们的诱因不同:
1.桥接模式对象自身有,沿着多个维度变化的趋势, 本身不稳定;
2.装饰者模式对象自身非常稳定, 只是为了增加新功能/增强原功能。
参考
【文中代码】https://github.com/boilingfrog/design-pattern-learning/tree/master/装饰器模式
【大话设计模式】https://book.douban.com/subject/2334288/
【极客时间】https://time.geekbang.org/column/intro/100039001
【装饰模式】https://boilingfrog.github.io/2021/11/13/使用go实现装饰模式/#装饰器模式