1.前言
装饰器模式也是结构型模式中的一种,在谈装饰器模式之前我们现在谈一个跟这个相关的话题,我们如何给类扩展功能呢?我能立马想到的就是这三种方式继承、部分类、扩展,也是常用的三种方式,部分类局限于必须是我们自定义的类才能用部分类扩展,如果我们是用的类库中的类想要扩展这个方法就不行,继承或许是大多数人能想到的方法,但设计模式有一个原则就是”组合大于继承的原则”,鼓励我们多用组合少用继承,因为继承的越多类会越来越”膨胀”,子类,子子类,甚至更多我们就会容易搞混,就像你记得你的父亲和祖父,曾祖父在网上估计能记得的很少了,所以类的继承也是如此,能少的继承就少的继承。下文会介绍他们之间的区别。生活中的装饰器模式的例子,圣诞节的时候,公司给我们搞了一个活动,各个部门一个原始的圣诞树,然后让各个部门自己去装饰,看哪个部门装饰的有创意,原本光秃秃的圣诞树是没有什么功能的,经过各个部门小伙伴的装饰,使其具有了放音乐的功能,具有了金光闪闪的功能等等,这就可以理解为经过装饰让他的功能更加丰富了,下面附带一下我们公司各个部门的装饰圣诞树了,你觉得哪个装饰的最好看呢?说了一通扩展类的功能方法,那么装饰器模式又是一种什么样的模式呢?
扩展方法跟装饰器模式的区别
扩展方法和装饰器模式都是扩展,那他们有什么异同呢?他们的相同点上文说了可以不修改之前类的前提下,扩展原类的功能,这个功能不仅仅局限扩展类中的功能方法,还有一个扩展功能是指扩展类中方法的功能,都是对这个类的功能做扩展,可以理解为一个是添加类方法,一个是扩展类中方法的功能,这个也可以理解为继承中的重写方法,不过一个是重写一个是扩展的区别。不同点就是扩展方法是静态的,装饰器模式是动态扩展功能。那么何为静态和动态。扩展方法是static类的方法,在编译时就已经编译好了,装饰器模式扩展是在运行时扩展的。
基本介绍
装饰器模式(Decorator Pattern),允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。这里的重点是保持类方法签名完整性的前提下,然后扩展方法,不能修改原类的方法功能,这个在上文也有介绍跟重写的区别。
UML
- Component:接口,定义一个抽象接口,真实对象和装饰对象具有相同的接口,以便动态的添加职责。
- ConcreteComponent:具体的对象。
- Decorator:装饰类,继承了Component,从外类来扩展Component类的功能,并且持有一个构建引用,进行请求转发。
- ConcreteDecorator:具体装饰类,用于给实际对象添加职责。
为什么要用装饰器模式
要回答这种问题就是看装饰器模式解决了什么问题,不用装饰器模式会有哪些弊端?上文提到过如果用继承重写的话,如果子类过多会造成类的”膨胀”,也不符合设计模式的推荐原则组合大于继承的原则。
跟其他设计模式的区别和联系
符合”组合关系”的设计模式有很多,比如之前讲过的代理模式、桥接模式,还有现在的装饰器模式,尽管他们结构很类似,但每种设计模式的意图是不同的。代理模式附加的功能跟原始类是无关的,这种跟扩展方法和部分类更类似,我们来回顾一下之前代理模式中讲到的animation的代理,代理类调用了Unity底层的api Animation然后做了一些方法的调用,如果想要扩展方法那就跟之前类的功能是不相关的,但如果是调用了底层Animation的方法然后又做了一些方法功能的扩展这又有点类似装饰器模式了,不过代理模式可以选择在原来类方法中进行挑选,他的侧重点是添加一层访问,可以有效做到权限分配。而在装饰器模式中,装饰器类附加的是跟原始类功能相关的增强功能,他的重点是在扩展原类的方法。
类库源码解析
.net framework类库中关于IO的设计,