装饰模式意图
动态的给一个对象增加一些额外的职责,就增加功能来说,装饰模式相比生产子类更为灵活
装饰模式适用性
以下情况适合使用装饰模式:
.在不影响其他对象的情况下,动态、透明的方式给单个对象添加职责。
.处理那些可以撤销的职责。
.当不成采用生成子类的方法进行扩充时。一种情况是,可能会有大量独立的扩展,为支持每一种组合将产生大量的子类。使得子类数目呈现爆炸性增长。另外一种情况可能是类型定义被隐蔽,或类定义不能用于生产子类。
结构
装饰模式效果
使用装饰模式有以下优点:
1)使用装饰模式比静态继承更加灵活,和对象的静态继承(golang中不存在多重继承)相比,装饰模式提供更加灵活的向对象增加职责的方式。可以用添加和分离的方法,用装饰在运行时刻增加和删除职责。相比之下,继承机制要求为每个类添加的职责创建一个新的子类,并且会增加系统的复杂度。此外,为一个特定的Component类提供多个不同的Decorator类,可以使得一些职责进行混合和匹配。
2)避免在层次结构高层的类有太多复杂的特征。装饰模式提供一种“即用即付”的方式来添加职责。并不试图在一个复杂的可定制的类中支持所有可预见的特征,相反,可以定义一个简单的类,并且应用Decorator类给他逐渐地添加功能。可以用简单的部件组合出复杂的功能。这样,应用程序不必为不需要的特征付出代价。同时也不依赖于Decorator所扩展的类型而独立定义新的类型的Decorator。拓展一个复杂的类型时,很可能会暴露与添加的职责无关的细节。
同时装饰模式也会有一些缺点:
有很多小对象。采用装饰模式进行系统设计时,往往会产生看上去很类似的小对象,这些对象仅仅在相互连接方式有所不同。这对于对系统很熟悉的人来说,很容易组装,对需求进行定制。而对开始接触系统的人来说,却很难学习。同时在排查错误的时候,需要排查大量的小类,导致排错也比较困难。
总体上来说,装饰模式对熟悉系统的开发来说特别方便,但是会增加学习难度和降低可维护性。
实现
package main
import (
"fmt"
)
type Company interface {
Showing()
}
type BaseCompany struct {
}
func (pB *BaseCompany) Showing() {
fmt.Println("公司有老板,有前台,有人事...")
}
type DevelopingCompany struct {
Company
}
func (pD *DevelopingCompany) AddWorker() {
fmt.Println("还有开发、测试、财务人员")
}
func (pD *DevelopingCompany) Showing() {
fmt.Println("发展中公司中:")
pD.Company.Showing()
pD.AddWorker()
}
type BigCompany struct {
Company
}
func (pD *BigCompany) AddWorker() {
fmt.Println("除此之外,个职能人员应有尽有")
}
func (pD *BigCompany) Showing() {
fmt.Println("大型公司中:")
pD.Company.Showing()
pD.AddWorker()
}
func main() {
company := &BaseCompany{}
developingCompany := &DevelopingCompany{Company: company}
developingCompany.Showing()
bigCompany := &BigCompany{Company: developingCompany}
bigCompany.Showing()
return
}
运行结果:
发展中公司中:
公司有老板,有前台,有人事…
还有开发、测试、财务人员
大型公司中:
发展中公司中:
公司有老板,有前台,有人事…
还有开发、测试、财务人员
除此之外,个职能人员应有尽有