当前位置:网站首页>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等文章, 可能有你想要了解的技能知识点哦~
边栏推荐
- studio All flavors must now belong to a named flavor dimension. Learn more
- Grid connection - Analysis of low voltage ride through and island coexistence
- Xctf mobile--app1 problem solving
- The latest version of blind box mall thinkphp+uniapp
- Seven second order ladrc-pll structure design of active disturbance rejection controller
- RedHat5 安装Socket5代理服务器
- 【习题六】【数据库原理】
- 【习题七】【数据库原理】
- Drop down refresh conflicts with recyclerview sliding (swiperefreshlayout conflicts with recyclerview sliding)
- 【判断题】【简答题】【数据库原理】
猜你喜欢

Sword finger offer07 Rebuild binary tree

(最新版) Wifi分销多开版+安装框架

Powerful avatar making artifact wechat applet

idea将web项目打包成war包并部署到服务器上运行

Eureka self protection

剑指Offer06. 从尾到头打印链表

Sword finger offer06 Print linked list from end to end

Alibaba is bigger than sending SMS (user microservice - message microservice)

剑指Offer04. 二维数组中的查找【中等】

ncnn神经网络计算框架在香橙派OrangePi 3 LTS开发板中的使用介绍
随机推荐
剑指Offer03. 数组中重复的数字【简单】
Openstack node address change
电压环对 PFC 系统性能影响分析
ORM use of node -serialize
Nodejs+Express+MySQL实现登陆功能(含验证码)
Summary of error prone knowledge points: Calculation of define s (x) 3*x*x+1.
Four problems and isolation level of MySQL concurrency
【数据库原理及应用教程(第4版|微课版)陈志泊】【SQLServer2012综合练习】
[problem exploration and solution of one or more filters or listeners failing to start]
Approve iPad, which wants to use your icloud account
Dix règles de travail
studio All flavors must now belong to a named flavor dimension. Learn more
Xctf mobile--app2 problem solving
Kotlin notes - popular knowledge points asterisk (*)
alright alright alright
Glide question you cannot start a load for a destroyed activity
记录自己vulnhub闯关记录
Alibaba is bigger than sending SMS (user microservice - message microservice)
Application of ncnn neural network computing framework in orange school orangepi 3 lts development board
【数据库原理及应用教程(第4版|微课版)陈志泊】【第六章习题】