装饰模式(Decorator),动态地给被装饰的对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更加灵活。
Component
抽象组件,扮演底层的被装饰者。
ConcreteComponent
是具体的底层被装饰者。
Decorator
装饰基类,为被装饰者提供“装饰”功能。
ComponentDecorator
具体的装饰者,提供具体的装饰。
Component
抽象组件类
/**
* @create on 2020/7/5 22:06
* @description 抽象组件类
* @author mrdonkey
*/
abstract class Component {
abstract fun operation()
}
ConcreteComponent
具体的组件类
/**
* @create on 2020/7/5 22:08
* @description 具体组件
* @author mrdonkey
*/
class ConcreteComponent : Component() {
override fun operation() {
println("具体组件对象的操作")
}
}
Decorator
装饰基类,里面维持了一个被装饰者,即待装饰的组件。
/**
* @create on 2020/7/5 22:09
* @description 装饰类
* @author mrdonkey
*/
open class Decorator : Component() {
lateinit var component: Component//待装饰的组件
override fun operation() {
if (this::component.isInitialized) {
component.operation()//执行component的operation方法
}
}
}
ConcreteDecoratorA
具体的装饰类,实现具体的装饰功能。
/**
* @create on 2020/7/5 22:14
* @description 具体的装饰者
* @author mrdonkey
*/
class ConcreteDecoratorA: Decorator() {
override fun operation() {
super.operation()
println("具体装饰对象A的操作")
addBehaviorA()
}
/**
* 装饰者A独有方法
*/
private fun addBehaviorA(){
}
}
…省略ConcreteDecorator
Client
客户端
/**
* @create on 2020/7/5 22:18
* @description 客户端
* @author mrdonkey
*/
class Client {
companion object {
@JvmStatic
fun main(args: Array<String>) {
val component = ConcreteComponent()
val decoratorA = ConcreteDecoratorA()
val decoratorB = ConcreteDecoratorB()
//decoratorA包装component
//decoratorB包装decoratorA
//....层层装饰(包装)
//本质上将装饰的component对象串联成单链表,最终逐个调用其operation方法
decoratorA.component = component
decoratorB.component = decoratorA
decoratorB.operation()
}
}
}
装饰模式是利用 setComponent
来对对象进行层层包装的,这样每个对象的实现就和如何使用的这个对象分离开了,每个装饰对象只关心自己的功能,不需要关心如何被添加到对象链
中。
测试结果
具体组件对象的操作
具体装饰对象A的操作
具体装饰对象B的操作
人每天的装扮也是一个装饰模式应用。
人作为底层被装饰者,穿上衣服和裤子、鞋子都是被装饰的过程。
Person
人,基础的被装饰对象
/**
* @create on 2020/7/5 22:27
* @description 人
* @author mrdonkey
*/
open class Person constructor() {
private var name: String? = null
constructor(name: String) : this() {
this.name = name
}
open fun show() {
println("$name 今天的装扮")
}
}
Finery
服饰类
/**
* @create on 2020/7/5 22:30
* @description 服饰类
* @author mrdonkey
*/
open class Finery : Person() {
lateinit var component: Person//被装饰对象
override fun show() {
if (this::component.isInitialized) {
component.show()
}
}
}
TShirt
t 恤类,具体的装饰
/**
* @create on 2020/7/5 22:34
* @description T恤
* @author mrdonkey
*/
class TShirts : Finery() {
override fun show() {
println("穿上T恤")
super.show()
}
}
Jeans
和Shoes
省略…
Client
客户端
/**
* @create on 2020/7/5 22:37
* @description 客户端
* @author mrdonkey
*/
class Client {
companion object {
@JvmStatic
fun main(args: Array<String>) {
val zs = Person("张三")
val shoes = Shoes()
val tShirts = TShirts()
val jeans = Jeans()
tShirts.component = zs//张三穿上t恤
jeans.component = tShirts//张三穿上牛仔
shoes.component = jeans//张三穿上鞋
shoes.show()//穿完了!
//...可以为张三换其他的装饰
}
}
}
测试结果
穿上鞋子
穿上牛仔裤
穿上T恤
张三 今天的装扮
它把每个要装饰的功能放在单独的类中,并让这个类包装它所要装饰的对象(而不是向旧类中添加新的代码,增加旧类的复杂度)。因此,当需要执行特殊行为时,客户代码就可以在运行时根据需要有选择地、按顺序地使用装饰功能包装对象。
在内部组装完成,最后才显示出来
;但建造者模式建造过程是稳定的,而装饰者的装饰过程是不稳定的。