当前位置:网站首页>Kotlin - 改良装饰者模式
Kotlin - 改良装饰者模式
2022-07-03 12:03:00 【GitLqr】
欢迎关注微信公众号:FSA全栈行动
- Kotlin - 改良工厂模式
- Kotlin - 改良构建者模式
- Kotlin - 改良观察者模式
- Kotlin - 改良策略模式
- Kotlin - 改良迭代器模式
- Kotlin - 改良责任链模式
- Kotlin - 改良装饰者模式
一、前言
- 装饰者模式
- 作用:在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。
- 本质:该模式通过创建一个包装对象,来包裹真实的对象。
- 核心操作:
- 创建一个装饰类,包含一个被装饰类的实例
- 装饰类重写所有被装饰类的方法
- 在装饰类中对需要增强的功能进行扩展
二、使用装饰者模式
- 例子:枪支部件
- 重点:装饰器类设计(实现被装饰类相同的接口,构造器接收被装饰类的接口实例对象)
像绝地求生这种大型射击游戏,里面的枪支系统是很复杂的,有很多种枪,而且几乎每种枪上都可以装配各种各样的部件,比如消声器、八倍镜之类的,部件的作用各不相同,有的可以增加火力,有的可以提高精确度,等等,现在我们来简单设计一下这个枪支系统,枪有很多种,所以需要定义一个接口来描述枪都有哪些能力,供后续扩展各种新枪:
/** * 枪支接口 * * @author GitLqr */
interface Gun {
/** * 攻击力 */
fun attack(): Float
/** * 噪音 */
fun noise(): Float
/** * 生产日期 */
fun prodDate(): String
}
/** * Ump9 * * @author GitLqr */
class Ump9Gun : Gun {
override fun attack() = 100f
override fun noise() = 20f
override fun prodDate() = "2020-02-18"
}
这里只实现了 Ump9 这个型号的枪,后续还可以根据需要扩展,现在来想想枪支部件怎么设计?在 Java 中,给一个类扩展行为有两种选择:
- 设计一个继承它的子类
- 使用装饰者模式对该类进行装饰
那么枪支部件合适用继承方式来设计吗?显然不合适,因为一个部件可以装配在不只一种枪上,所以继承这种方式排除。另一种方式,使用装饰者模式有一个很大的优势,在于符合“组合优于继承”的设计原则,我们知道,部件可以和任意枪组合,显示,使用装饰者模式来设计枪支部件是一个不错的选择:
/** * 枪支部件 * * @author GitLqr */
abstract class GunPart(protected val gun: Gun) : Gun
/** * 消声器 * * @author GitLqr */
class Muffler(gun: Gun) : GunPart(gun) {
override fun attack() = gun.attack() - 5
override fun noise() = 0f
override fun prodDate() = gun.prodDate()
}
/** * 燃烧子弹 * * @author GitLqr */
class FireBullet(gun: Gun) : GunPart(gun) {
override fun attack() = gun.attack() + 200
override fun noise() = gun.noise()
override fun prodDate() = gun.prodDate()
}
程序设计时,装饰器(部件)会引用被装饰实例(枪),并实现被装饰实例的所有接口,然后在需要增强的接口方法中加入增强逻辑。因为枪支部件 GunPart
接收 Gun
类型构造参数,而且本身也是 Gun
接口的实现类,所以,可以让多种枪支部件 GunPart
嵌套修饰枪实例:
// 使用
var ump9: Gun = Ump9Gun()
println("装配前:ump9 攻击力 ${
ump9.attack()},噪音 ${
ump9.noise()}")
ump9 = Muffler(FireBullet(ump9)) // 装配了 燃烧子弹、消声器 的ump9
println("装配后:ump9 攻击力 ${
ump9.attack()},噪音 ${
ump9.noise()}")
// 输出
装配前:ump9 攻击力 100.0,噪音 20.0
装配后:ump9 攻击力 295.0,噪音 0.0
三、改良装饰者模式
- 例子:枪支部件
- 重点:类委托(
by
关键字)
在上面的例子中,装饰者模式可以很好的解决实例组合的情况,但是代码还是显得比较啰唆,因为需要重写所有的装饰对象方法,所以可能会存在大量样板代码。比如 FireBullet
只装饰增强 attack()
方法,而 noise()
、prodDate()
均不做修改,但还要是把这两个方法重写一遍。Kotlin 中有类委托特性,利用 by
关键字,将装饰类的所有方法委托给一个被装饰的类对象,然后只需覆写装饰的方法即可:
/** * 枪支部件 * * @author GitLqr */
abstract class GunPart(protected val gun: Gun) : Gun by gun
/** * 消声器 * * @author GitLqr */
class Muffler(gun: Gun) : GunPart(gun) {
override fun attack() = gun.attack() - 5
override fun noise() = 0f
}
/** * 燃烧子弹 * * @author GitLqr */
class FireBullet(gun: Gun) : GunPart(gun) {
override fun attack() = gun.attack() + 200
}
可以看到,使用类委托之后,装饰类 FireBullet
中的样板代码不用重写了,从而减少了代码量。
如果文章对您有所帮助, 请不吝点击关注一下我的微信公众号:FSA全栈行动, 这将是对我最大的激励. 公众号不仅有Android技术, 还有iOS, Python等文章, 可能有你想要了解的技能知识点哦~
边栏推荐
- 【数据挖掘复习题】
- 【数据库原理及应用教程(第4版|微课版)陈志泊】【SQLServer2012综合练习】
- Airflow installation jump pit
- Alibaba is bigger than sending SMS (user microservice - message microservice)
- Sword finger offer05 Replace spaces
- Sword finger offer14 the easiest way to cut rope
- Cache penetration and bloom filter
- [exercise 6] [Database Principle]
- Create a dojo progress bar programmatically: Dojo ProgressBar
- Public and private account sending prompt information (user microservice -- message microservice)
猜你喜欢
Differences between initial, inherit, unset, revert and all
Low code platform international multilingual (I18N) technical solution
【数据库原理及应用教程(第4版|微课版)陈志泊】【SQLServer2012综合练习】
idea将web项目打包成war包并部署到服务器上运行
Detailed explanation of the most complete constraintlayout in history
Application of ncnn Neural Network Computing Framework in Orange Pi 3 Lts Development Board
The latest version of lottery blind box operation version
公纵号发送提示信息(用户微服务--消息微服务)
Public and private account sending prompt information (user microservice -- message microservice)
最新版盲盒商城thinkphp+uniapp
随机推荐
Xctf mobile--app3 problem solving
[review questions of database principles]
Simple use and precautions of kotlin's array array and set list
最新版抽奖盲盒运营版
【数据库原理及应用教程(第4版|微课版)陈志泊】【第七章习题】
C graphical tutorial (Fourth Edition)_ Chapter 15 interface: interfacesamplep268
阿里 & 蚂蚁自研 IDE
Two solutions of leetcode101 symmetric binary tree (recursion and iteration)
[Exercice 5] [principe de la base de données]
十條職場規則
自抗扰控制器七-二阶 LADRC-PLL 结构设计
Low code platform international multilingual (I18N) technical solution
The solution to change the USB flash disk into a space of only 2m
Tensorflow binary installation & Failure
Keep learning swift
ImportError: No module named examples. tutorials. mnist
The latest version of lottery blind box operation version
Glide 4.6.1 API initial
[exercise 5] [Database Principle]
Four problems and isolation level of MySQL concurrency