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

前言

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

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

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

实现

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

kotlin 复制代码
interface BitmapProcessor {
    fun process(bitmap: Bitmap): Bitmap
}


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

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

kotlin 复制代码
abstract class BitmapProcessDecorator(private val process: BitmapProcessor) : BitmapProcessor {
    override fun process(bitmap: Bitmap): Bitmap {
        return process.process(bitmap)
    }
}

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

kotlin 复制代码
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)
    }
}

客户端创建对应的装饰器

kotlin 复制代码
//创建原始图片对象
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 的情况下为每个项添加装饰比如分割线、边距等。

kotlin 复制代码
/**
 * 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方法。

kotlin 复制代码
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)
        }
    }
}

总结

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

相关推荐
旺代2 小时前
C++设计模式(单例模式)
c++·单例模式·设计模式
LightOfNight2 小时前
【设计模式】创建型模式之单例模式(饿汉式 懒汉式 Golang实现)
单例模式·设计模式·golang
那年星空11 小时前
Flutter 设计模式全面解析:抽象工厂
flutter·设计模式·架构
博风12 小时前
设计模式:10、外观模式
设计模式·外观模式
你好helloworld14 小时前
设计模式之观察者模式
观察者模式·设计模式
zzzhpzhpzzz18 小时前
设计模式——抽象工厂模式
设计模式·抽象工厂模式
阳光开朗_大男孩儿19 小时前
组合设计模式
c++·设计模式·组合模式·组合设计模式
编程、小哥哥20 小时前
设计模式之代理模式(模拟mybatis-spring中定义DAO接口,使用代理类方式操作数据库原理实现场景)
设计模式·mybatis·代理模式
zhangphil21 小时前
Android叠加双RecyclerView ScaleGestureDetector AnimatorSet动态放大缩小,Kotlin(1)
android·kotlin
白茶等风1213821 小时前
Unity 设计模式-状态模式(State Pattern)详解
设计模式·状态模式