【Kotlin设计模式】Kotlin实现装饰器模式

news2024/9/23 19:20:59

前言


装饰器模式(Decorator Pattern),用于动态地为对象添加新功能,而无需修改其结构,通过使用不用装饰类及这些装饰类的排列组合,可以实现不同的功能和效果,但是这样的效果就是会增加很多类,过度使用增加程序的复杂性。

适配器模式主要包括以下几个角色:

1、组件接口(Component:定义一个对象接口,可以有基本功能或抽象功能。
2、具体组件(ConcreteComponent:实现组件接口的基本功能。
3、装饰器(Decorator:持有一个组件对象的引用,并实现组件接口。
4、具体装饰器(ConcreteDecorator:实现了装饰器,并为组件对象添加了具体的附加功能。

在这里插入图片描述


实现


以下例子实现装饰器模式,定义图像处理接口BitmapProcessor,提供处理图片方法方法,具体组件实现基本的 BitmapProcessor,提供原始的 Bitmap对象。


interface BitmapProcessor {
    fun process(bitmap: Bitmap): Bitmap
}


class BasicBitmapProcessor(private val bitmap: Bitmap) : BitmapProcessor {
    override fun process(bitmap: Bitmap): Bitmap {
        return this.bitmap
    }
}

实现一个通用的装饰器,持有一个 BitmapProcessor 对象的引用。


abstract class BitmapProcessDecorator(private val process: BitmapProcessor) : BitmapProcessor {
    override fun process(bitmap: Bitmap): Bitmap {
        return process.process(bitmap)
    }
}

实现具体装饰器继承,选择图片、缩放图片功能。


class RotateDecorator(process: BitmapProcessor, private val angle:Float): BitmapProcessDecorator(process) {

    override fun process(bitmap: Bitmap): Bitmap {
        val matrix = Matrix().apply {
            postRotate(angle)
        }
        return Bitmap.createBitmap(bitmap, 0, 0, bitmap.width, bitmap.height, matrix, true)
    }
}



class ScaleDecorator(process: BitmapProcessor, private val sx: Float, private val sy: Float) : BitmapProcessDecorator(process) {

    override fun process(bitmap: Bitmap): Bitmap {
        val matrix = Matrix().apply {
            postScale(sx, sy)
        }
        return Bitmap.createBitmap(bitmap, 0, 0, bitmap.width, bitmap.height, matrix, true)
    }
}

客户端创建对应的装饰器


//创建原始图片对象
val originalBitmap = BitmapFactory.decodeResource(resources, R.drawable.ic_launcher_foreground)

//创建具体图片处理对象
val basicProcessor = BasicBitmapProcessor(originalBitmap)

//创建图片旋转装饰器
val rotateDecorator = RotateDecorator(basicProcessor, 45.0f)
rotateDecorator.process(originalBitmap)   //旋转90度

//创建图片缩放装饰器
val scaleDecorator = ScaleDecorator(basicProcessor, 2.0f, 2.0f)
scaleDecorator.process(originalBitmap)    //缩放2倍

//处理图片,显示
val processorBitmap= basicProcessor.process(originalBitmap)
mBinding.image.setImageBitmap(processorBitmap)

        

Android中,经常使用的控件RecyclerView中就提供了装饰器模式的应用,ItemDecoration它允许你在不修改原始 RecyclerView 的情况下为每个项添加装饰比如分割线、边距等。


/**
 * An ItemDecoration allows the application to add a special drawing and layout offset
 * to specific item views from the adapter's data set. This can be useful for drawing dividers
 * between items, highlights, visual grouping boundaries and more.
 */
public abstract static class ItemDecoration {
   /**
    * Draw any appropriate decorations into the Canvas supplied to the RecyclerView.
    * Any content drawn by this method will be drawn before the item views are 
    */
   public void onDraw(@NonNull Canvas c, @NonNull RecyclerView parent, @NonNull State state) {
       onDraw(c, parent);
   }

   /**
    * Draw any appropriate decorations into the Canvas supplied to the RecyclerView.
    * Any content drawn by this method will be drawn after the item views are drawn
    */
   public void onDrawOver(@NonNull Canvas c, @NonNull RecyclerView parent,
           @NonNull State state) {
       onDrawOver(c, parent);
   }


   /**
    * Retrieve any offsets for the given item. Each field of <code>outRect</code> specifies
    * the number of pixels that the item view should be inset by, similar to padding or margin.
    * The default implementation sets the bounds of outRect to 0 and returns.
    *
    * <p>
    * If this ItemDecoration does not affect the positioning of item views, it should set
    * all four fields of <code>outRect</code> (left, top, right, bottom) to zero
    * before returning.
    *
    * <p>
    * If you need to access Adapter for additional data, you can call
    * {@link RecyclerView#getChildAdapterPosition(View)} to get the adapter position of the
    * View.
    *
    * @param outRect Rect to receive the output.
    * @param view    The child view to decorate
    * @param parent  RecyclerView this ItemDecoration is decorating
    * @param state   The current state of RecyclerView.
    */
   public void getItemOffsets(@NonNull Rect outRect, @NonNull View view,
           @NonNull RecyclerView parent, @NonNull State state) {
       getItemOffsets(outRect, ((LayoutParams) view.getLayoutParams()).getViewLayoutPosition(),
               parent);
   }
}
 

下面实现为RecyclerView的条目添加分割线,继承ItemDecoration类,实现onDrawOver方法。


class DividerItemDecoration(context: Context) : RecyclerView.ItemDecoration() {

    private val divider: Drawable?

    init {
        val styledAttributes = context.obtainStyledAttributes(intArrayOf(android.R.attr.listDivider))
        divider = styledAttributes.getDrawable(0)
        styledAttributes.recycle()
    }

    override fun onDrawOver(c: Canvas, parent: RecyclerView, state: RecyclerView.State) {
        val left = parent.paddingLeft
        val right = parent.width - parent.paddingRight

        val childCount = parent.childCount
        for (i in 0 until childCount - 1) {
            val child = parent.getChildAt(i)
            val params = child.layoutParams as RecyclerView.LayoutParams
            val top = child.bottom + params.bottomMargin
            val bottom = top + divider!!.intrinsicHeight

            divider.setBounds(left, top, right, bottom)
            divider.draw(c)
        }
    }
}


总结


装饰器模式在需要动态扩展对象功能的场景中非常有用,可以提高灵活性和复用性。然而,它也可能增加系统的复杂性,并带来一定的性能开销。在使用装饰器模式时,需要权衡其优缺点,并根据实际需求做出合理的设计决策。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2078404.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

debian12 - rsyslog的安装/配置/使用

文章目录 debian12 - rsyslog的安装/配置/使用概述笔记实现main.cppmy_syslog.hmy_syslog.cppMakefileMakefile的准备工作END debian12 - rsyslog的安装/配置/使用 概述 以前在debian7.5中用syslog可以。 现在准备在debian12虚拟机中做个rsyslog的实验&#xff0c;看syslog还…

2024年PDF转换成PPT三步走,职场小白秒变高手

这个信息满天飞的时代&#xff0c;我们几乎天天都得处理一堆文件&#xff0c;PDF和PPT这对搭档简直就是我们工作学习中的老面孔。你有没有碰到过这种头疼事&#xff1a;急着要把PDF转成PPT来准备个演讲&#xff0c;但就是找不到个又快又好使的招&#xff1f;别慌&#xff0c;今…

一文搞懂大模型!基础知识、 LLM 应用、 RAG 、 Agent 与未来发展

LLM 探秘&#xff1a;想要深入了解人工智能界的“新宠”大型语言模型&#xff08;LLM&#xff09;吗&#xff1f;本文将带你走进 LLM 的世界&#xff0c;从入门知识到实际应用&#xff0c;全方位解读这个充满魔力的“大模型”。我们将一起揭开 LLM 的神秘面纱&#xff0c;领略其…

代码随想录算法训练营第三十九天 | 198.打家劫舍 , 213.打家劫舍II , 337.打家劫舍III

目录 198.打家劫舍 思路 1.确定dp数组&#xff08;dp table&#xff09;以及下标的含义 2.确定递推公式 3.dp数组如何初始化 4.确定遍历顺序 5.举例推导dp数组 方法一&#xff1a; 动态规划-一维 方法二&#xff1a;动态规划-二维 方法三&#xff1a;动态规划-两个变…

零知识证明-基础数学(二)

零知识证明(Zero—Knowledge Proof)&#xff0c;是指一种密码学工具&#xff0c;允许互不信任的通信双方之间证明某个命题的有效性&#xff0c;同时不泄露任何额外信息 导数、偏导数 ,互质数&#xff0c;费马小定理&#xff0c;欧拉定理 1 导数 导数是微积分学中的重要概念&am…

从《黑神话:悟空》看中国3A游戏之路:历史回顾与未来展望

近年来&#xff0c;随着中国游戏行业的不断发展&#xff0c;一款名为《黑神话&#xff1a;悟空》的游戏引发了全球的广泛关注。这款游戏不仅在视觉效果和动作设计上令人惊艳&#xff0c;还被誉为中国3A游戏的里程碑。然而&#xff0c;从《黑神话&#xff1a;悟空》的发布&#…

STM32-PWM驱动呼吸灯——HAL库

&#xff08;根据B站up主keysking的STM32教程视频的笔记&#xff09; 【STM32】动画讲解轻松学会STM32的PWM_哔哩哔哩_bilibili 什么是PWM&#xff1f; PWM&#xff0c;全称为脉冲宽度调制&#xff08;Pulse Width Modulation&#xff09;&#xff0c;是一种调制技术&#xf…

对各项数据的统计汇总,集中展示,便于查看厂区情况的智慧物流开源了。

智慧物流视频监控平台是一款功能强大且简单易用的实时算法视频监控系统。它的愿景是最底层打通各大芯片厂商相互间的壁垒&#xff0c;省去繁琐重复的适配流程&#xff0c;实现芯片、算法、应用的全流程组合&#xff0c;从而大大减少企业级应用约95%的开发成本。构建基于Ai技术的…

【云原生】Kubernetes中常见的Pod故障排查定位与解决方案

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全…

3D环绕音效增强软件 Boom3D for Mac v2.0.2 中文破解版下载

Boom3D for Mac 专业的3D环绕音效增强软件中文版&#xff0c;Boom 3D是适用于Mac和Windows系统的专业音效增强软件&#xff0c;旨在通过播放器&#xff0c;媒体或流媒体服务等介质&#xff0c;在不同类型的耳机上以3D环绕效果播放媒体内容。您无需使用昂贵的耳机或其他附加环绕…

第十四章- 面对墙壁

这是最后的例子&#xff1a;一个完整的游戏。 我们添加键盘快捷键并引入鼠标事件到CannonField。我们在CannonField周围放一个框架并添加一个障碍物&#xff08;墙&#xff09;使这个游戏更富有挑战性。 lcdrange.h包含LCDRange类定义lcdrange.cpp包含LCDRange类实现cannon.h…

Linux 必备:“lsof” 命令 —— 解开系统资源的神秘密码

lsof 似侦探&#xff0c;揭示 Linux 中文件进程关系。图文指南助您探索。 lsof应急排查的作用 发现非法连接&#xff0c;检测未经授权的访问或攻击。定位服务故障&#xff0c;查看是否有进程占用关键端口。找出资源占用过高的进程&#xff0c;优化系统性能。追踪恶意软件的异…

博主正在AI+宠物创业中...

最近开始创业啦&#xff0c;csdn上没太大时间一一回复大家&#xff0c;说一声抱歉啦&#xff01; AI宠物创业中&#xff0c;宠有灵犀CTO&#xff0c;北大硕士 双学位 前阿里巴巴达摩院&#xff0c;邮箱17387842007163.com 我们瞄准了宠物赛道&#xff0c;做的是 供应链电商社交…

One-for-All:上交大提出视觉推理的符号化与逻辑推理分离的新范式 | ECCV 2024

通过对多样化基准的严格评估&#xff0c;论文展示了现有特定方法在实现跨领域推理以及其偏向于数据偏差拟合方面的缺陷。从两阶段的视角重新审视视觉推理&#xff1a;&#xff08;1&#xff09;符号化和&#xff08;2&#xff09;基于符号或其表示的逻辑推理&#xff0c;发现推…

罐装食品检测检测系统源码分享 # [一条龙教学YOLOV8标注好的数据集一键训练_70+全套改进创新点发刊_Web前端展示]

罐装食品检测检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer Vis…

一起学习LeetCode热题100道(57/100)

57.电话号码的字母组合(学习) 给定一个仅包含数字 2-9 的字符串&#xff0c;返回所有它能表示的字母组合。答案可以按 任意顺序 返回。 给出数字到字母的映射如下&#xff08;与电话按键相同&#xff09;。注意 1 不对应任何字母。 示例 1&#xff1a; 输入&#xff1a;digit…

ETL数据集成丨实现SQLServer数据库的高效实时数据同步

SQL Server&#xff0c;作为一款功能强大的关系型数据库管理系统&#xff08;RDBMS&#xff09;&#xff0c;在企业级应用中占据着举足轻重的地位。它不仅提供了可靠的数据存储与管理能力&#xff0c;还集成了高级数据分析、报表服务、集成服务以及商业智能等功能&#xff0c;为…

如何使用 500 多个表构建企业级 AI 查询向导

迄今为止的旅程&#xff1a;Confluence Agent 回顾 在深入研究 SQL Agent 之前&#xff0c;让我们先简单回顾一下我们开发的 Confluence Agent&#xff1a; 元数据提取&#xff1a;捕获我们的知识库的结构。内容提取&#xff1a;提取文档的核心内容。格式处理&#xff1a;分离 …

台灯应该买什么样的才能护眼?适合孩子的护眼台灯挑选指南

2022年3月1日起&#xff0c;正式实施的《儿童青少年学习用品近视防控卫生要求》&#xff08;GB 40070-2021&#xff09;规定了与近视防控相关的读写作业台灯卫生要求。台灯应该买什么样的才能护眼&#xff1f;要求从照度、均匀度、显色指数、色温、防蓝光等方面去完善护眼台灯&…

如何利用 Go 语言开发高可用服务

高可用的含义是尽量减少服务的不可用&#xff08;日常维护或者突发系统故障&#xff09;时长&#xff0c;提升服务的可用时长。如何衡量一个服务的可用性呢&#xff1f;或许你也听说过&#xff0c;通常企业可能会要求服务的可用性能能够达到三个 9(也就是 99.9%)或者 4个 9 &am…