前言
装饰器模式属于结构型模式,这个类型的设计模式总结出了 类、对象组合后的经典结构,将类、对象的结构和使用解耦了,花式的去借用对象。
装饰器模式
使用场景:动态追加或者撤销功能,一般是给class扩展新功能,面向切面编程也是装饰器模式的体现。
理解:类、对象的结构和使用解耦,装饰器模式很好的诠释了动态功能追加,但是前提是功能接口得一致,这样看起来才是对功能得扩展。综上所见应该是动态的借用,然后暴露对外一致的接口,最后调用这个接口即可,这个借用的操作可以一直叠加,从而实现了无上限的装饰下去。比如ts中的装饰器又叫注解,给类加上注解就会扩展类的功能,给方法加上注解就会扩展方法的功能。ts的装饰器,给类扩展应该是在类的原型上做手脚,而给方法扩展应该是改写了原有方法,用新的方法替换旧方法。
namespace struct_mode_03 {
// 接口
interface IPhone {
run(): void;
}
// 产品类
class HongMiK30 implements IPhone {
run(): void {
console.log('运行红米K30手机')
}
}
// 装饰器
class PhoneDecorator implements IPhone {
phoneDecorator: IPhone
constructor(phoneDecorator: IPhone) {
this.phoneDecorator = phoneDecorator
}
run(): void {
this.phoneDecorator.run()
}
}
// 实体的装饰类
class FanPhoneDecorator extends PhoneDecorator {
constructor(phone: IPhone) {
super(phone)
}
run() {
super.run()
this.runFan()
}
runFan() {
console.log('安装手机电风扇,运行手机电扇')
}
}
// 实体的装饰类
class MemoryPhoneDecorator extends PhoneDecorator {
constructor(phone: IPhone) {
super(phone)
}
run() {
this.runMemory()
super.run() // ! 这里是super 不是 this
}
runMemory() {
console.log('硬件升级,加大内存')
}
}
// 使用 一:尝试一下功能的追加
{
const hongMiK30 = new HongMiK30()
const homeMiK30DecorateFan = new FanPhoneDecorator(hongMiK30)
const homeMiK30DecorateMemory = new MemoryPhoneDecorator(hongMiK30)
console.log('hongMiK30')
hongMiK30.run()
console.log('homeMiK30DecorateFan')
homeMiK30DecorateFan.run()
console.log('homeMiK30DecorateMemory')
homeMiK30DecorateMemory.run()
}
// 使用 二:动态的追加功能 面向对象
{
const hongMiK30 = new HongMiK30()
const homeMiK30DecorateFan = new FanPhoneDecorator(hongMiK30)
const homeMiK30DecorateMemory = new MemoryPhoneDecorator(homeMiK30DecorateFan)
console.log('homeMiK30DecorateMemory')
homeMiK30DecorateMemory.run()
}
// 使用三:动态的追加功能 AOP
{
type fnProtoTypeExpression = {
addBeforeFn(fn: Function): fnProtoTypeExpression,
addAfterFn(fn: Function): fnProtoTypeExpression,
}
const fnProtoType: fnProtoTypeExpression = Function.prototype as unknown as fnProtoTypeExpression
fnProtoType.addBeforeFn = function (boforeFn: Function) {
const that = this as unknown as Function;
return function (...args: any) {
boforeFn(...args)
return that(...args)
} as unknown as fnProtoTypeExpression
}
fnProtoType.addAfterFn = function (afterFn: Function) {
const that = this as unknown as Function;
return function (...args: any) {
const result = that(...args)
afterFn(...args)
return result
} as unknown as fnProtoTypeExpression
}
const callMethods1 = function callMethods1() {
console.log('调用 callMethods1')
} as unknown as fnProtoTypeExpression
const callMethods2 = function callMethods2() {
console.log('调用 callMethods2')
} as unknown as fnProtoTypeExpression
const callMethods3 = function callMethods3() {
console.log('调用 callMethods3')
} as unknown as fnProtoTypeExpression
(callMethods2
.addBeforeFn(callMethods1 as unknown as Function)
.addAfterFn(callMethods3 as unknown as Function) as unknown as Function)()
}
}