结构型模式-装饰者
java 中我们给一个类扩展功能,有两种选择:
- 设计继承他的子类
- 使用装饰者模式对该类进行装饰,然后对功能进行扩展。
装饰模式:用类委托减少样板代码
不是所有场景都能满足继承扩展,所以装饰模式能够解决问题
装饰者模式
在不必要改变原有类和继承的情况,动态扩展对象一个功能。该模式通过创建包装对象,来包裹真实对象。
- 创建一个包装类,包含一个需要装饰类的实例
- 装饰类重写被装饰类的方法。
- 在装饰类中对需要增强的功能进行扩展
组合优先继承,有时候会很啰嗦,可能存在大量样板代码,kotlin可以利用by关键字,将装饰类的所有方法委托给一个被装饰的类对象,然后只需要写装饰的方法即可。
interface MacBook{
fun getCost():Int
fun getDesc():String
fun getProDate():String
}
class MacBookPro:MacBook{
override fun getCost()=1000
override fun getDesc()="MacBook Pro"
override fun getProDate()="Late 2011"
}
class ProcessorUpgradeMacbookPro(val macbook:MacBook):MacBook by macbook{
override fun getCost() = macbook.getCost() + 299
override fun getDesc()= macbook.getDesc() + " 1G Memory"
}
fun main() {
val macBook =MacBookPro()
val updateMacbookPro = ProcessorUpgradeMacbookPro(macBook)
println(updateMacbookPro.getCost())
println(updateMacbookPro.getDesc())
println(updateMacbookPro.getProDate())
}
升级后cost变化需要重写getCost,desc变化重写getDesc。ProcessorUpgradeMacbookPro类将所有方法委托给了macbook对象,生产年份不需要重写。
如果不用委托,在不继承Macbook类的前提下,那么我们需要创建一个装饰类和被装饰类的公共父类抽象。
通过扩展代替装饰者
举个栗子,一个Printer绘图类,三个方法,分别绘制实线,虚线,和星号线
class Printer {
fun drawLine() {
println("————————————")
}
fun drawDottedLine() {
println("- - - - - - ")
}
fun drawStars() {
println("***********")
}
}
现在有个需求,希望在打印线开始和结束,分别打印开始和结束标记。
如果给每个绘制方法装饰新的增功能,非常冗余。所以,我们可以用扩展替代装饰模式。
fun Printer.startDraw(decrated:Printer.()->Unit){
println("+++start drawing+++")
decrated()
println("+++end drawing+++")
}
》》》》
fun main() {
Printer().run {
startDraw {
drawLine()
}
startDraw {
drawDottedLine()
}
startDraw {
drawStars()
}
}
}
总结一下Kotlin中的设计模式设计
- 改造工厂模式
- 内联函数简化抽象工厂
- 弱化构建者模式的使用
- 用委托属性实现观察者模式
- 高阶函数简化设计模式
- 重载iterator方法
- 偏函数实现责任链
- ADT实现状态模式
- 装饰着模式实现新思路:委托原来的类,用kotlin扩展替换装装饰者。
网友评论