Android 装饰者模式初探

简介: 前提最近刚换了一份工作,这段时间一直在熟悉公司的代码逻辑,从中受益颇多。里面的设计模式也挺多的,运用的那个潇洒飘逸,让我好生羡慕。自己对设计模式这块理解的不是特别的深入,能拿出手的也就那么几个,刚好最近也学习了一些设计模式。

前提

最近刚换了一份工作,这段时间一直在熟悉公司的代码逻辑,从中受益颇多。里面的设计模式也挺多的,运用的那个潇洒飘逸,让我好生羡慕。自己对设计模式这块理解的不是特别的深入,能拿出手的也就那么几个,刚好最近也学习了一些设计模式。所以,在这里斗胆写一下关于设计模式的文章,一方面是加深记忆,一方面是做一下总结。如果有不对的地方还请各位指正。

首先

1、 定义
动态地给一个对象添加一些额外的职责。就增加功能来说,装饰模式相比生成子类更为灵活。
2、 介绍

  • 装饰者模式是一种结构模式
  • 装饰者模式的运用挺广的,举一个不太恰当的例子。比如花,花有颜色,有寓意也有花语。如果是花的花语是:“我足以与你相配”并且寓意是:“天真、纯洁、尊敬、父爱”,那么她就是白玫瑰。如果花的花语是:“莫离 幸福,就是你属于我”,寓意是:“清纯,贞洁,质朴,玲珑”,那么她就是白茉莉。
  • 通常我们扩展类的功能是通过继承的方式来实现,但是装饰者模式是通过组合的方式来实现,这是继承的替代方案之一。

3、角色说明:

  • Component(抽象组件):接口或者抽象类,被装饰的最原始的对象。具体组件与抽象装饰角色的父类。
  • ConcreteComponent(具体组件):实现抽象组件的接口。
  • Decorator(抽象装饰角色):一般是抽象类,抽象组件的子类,同时持有一个被装饰者的引用,用来调用被装饰者的方法;同时可以给被装饰者增加新的职责。
  • ConcreteDecorator(具体装饰类):抽象装饰角色的具体实现。

其次

原理讲了那么多,也许有的人对于枯燥的原理早都没有好感了(我能说我看到原理很头疼吗?),下面用一个实例来给大家讲解一番,就以花举例。

  • 创建抽象组件
    这里是一个抽象花类,定义一个装修的方法:

    public abstract class Flower {
     //装饰方法(显示颜色)
    public abstract void showColor();
    }
    
  • 创建具体组件
    这里是一个具体花类,并且给花定义了寓意

    public class SpecificFlower extends  Flower{
    
    
    private static final String TAG=SpecificFlower.class.getSimpleName();
    
    @Override
    public void showColor() {
      Log.e(TAG,"花开花落花有时");
     }
    
    }
    
  • 创建抽象装饰角色
    要为花定义颜色寓意等,定义抽象的花的装饰类:

    public abstract class FlowerDecorator extends Flower {
    
    Flower mFlower;
    
    public FlowerDecorator(Flower mFlower) {
      this.mFlower = mFlower;
    }
    
    @Override
    public void showColor() {
      mFlower.showColor();
    }
    
    /**
     * 显示感情(寓意)
     */
    public void showEmotion(){
    
    }
    }
    
  • 创建具体的装饰类

我们要定义不同的花(白玫瑰和白茉莉),那么他们的寓意和花语也是不同的,下面具体实现是不同的:

/**
 * 
 * 具体装饰类(白玫瑰)
 */
  public class WhiteRose extends FlowerDecorator {

  private static final String TAG=SpecificFlower.class.getSimpleName();

  public WhiteRose(Flower mFlower) {
    super(mFlower);
  }

  @Override
  public void showColor() {
    super.showColor();
    Log.e(TAG,"我是白玫瑰,我的花语是:我足以与你相配");

  }

  @Override
  public void showEmotion() {
    super.showEmotion();
    Log.e(TAG,"我是白玫瑰,我的寓意是:天真、纯洁、尊敬、父爱");
  }
}

 /**
 * 
 * 具体装饰类(白茉莉)
 */

public class WhiteMolly extends FlowerDecorator {

private static final String TAG=SpecificFlower.class.getSimpleName();

public WhiteMolly(Flower mFlower) {
    super(mFlower);
}

@Override
public void showColor() {
    super.showColor();
    Log.e(TAG,"我是白茉莉,我的花语是:莫离 幸福,就是你属于我");
}

@Override
public void showEmotion() {
    super.showEmotion();
    Log.e(TAG,"我是白茉莉,我的寓意是:清纯,贞洁,质朴,玲珑 ");
 }
}
  • 调用实现(使用)

     Flower flower=new SpecificFlower();
     FlowerDecorator flowerDecorator= new WhiteMolly(flower);
     flowerDecorator.showColor();
     flowerDecorator.showEmotion();
     FlowerDecorator mFlower= new WhiteRose(flower);
     mFlower.showColor();
     mFlower.showEmotion();
    
  • 打印日志

    img_b142cbfaf1aa95c61e3517bb0d189250.png
    装饰者模式日志.png
  • 应用场景
    需要扩展一个类的功能,或给一个类增加附加功能时
    需要动态的给一个对象增加功能,这些功能可以再动态的撤销
    当不能采用继承的方式对系统进行扩充或者采用继承不利于系统扩展和维护时。

  • 优点
    采用组合的方式,可以动态的扩展功能,同时也可以在运行时选择不同的装饰器,来实现不同的功能。
    有效避免了使用继承的方式扩展对象功能而带来的灵活性差,子类无限制扩张的问题。
    被装饰者与装饰者解偶,被装饰者可以不知道装饰者的存在,同时新增功能时原有代码也无需改变,符合开放封闭原则。

  • 缺点
    装饰层过多的话,维护起来比较困难。
    如果要修改抽象组件这个基类的话,后面的一些子类可能也需跟着修改,较容易出错,装饰者模式虽好,切不可贪杯,用的太多,不容易处理。

最后

上面就是小可最近所学到的设计模式,如果有不对的地方还请给我大佬指正提点。源码就是文中所列出来的这些,如果需要尝试,复制粘贴即可实现。

感谢

Android的设计模式-装饰者模式

相关文章
|
程序员 Shell 数据格式
python股票量化交易(1)---K线图、均线与成交量绘制
python股票量化交易(1)---K线图、均线与成交量绘制
2674 0
python股票量化交易(1)---K线图、均线与成交量绘制
|
消息中间件 NoSQL Java
Redis监听Key的过期事件
在redis.conf配置文件中有个配置项:notify-keyspace-events " " ,默认是没有key的过期监听的,我们需要将其开启
2414 0
|
SQL 分布式计算 算法
手撕SparkSQL五大JOIN的底层机制
手撕SparkSQL五大JOIN的底层机制
542 0
|
API C语言 图形学
EasyX图形库学习(一、窗口创建函数initgraph、背景颜色设置setbkcolor、图形绘制函数)
EasyX图形库学习(一、窗口创建函数initgraph、背景颜色设置setbkcolor、图形绘制函数)
|
资源调度
vue3 + ts:watch(immediate、deep、$watch)
vue3 + ts:watch(immediate、deep、$watch)
363 0
vue3 + ts:watch(immediate、deep、$watch)
|
存储 监控 NoSQL
不改一行源码,实现 sentinel-dashboard 所有配置支持 apollo 持久化
虽然 sentinel 的设计非常优秀,基本上满足了流量治理的所有需求,但是 sentinel-dashboard 的配置都是存储在内存,在服务重启后就会丢失。要在生产环境上使用 sentinel 就需要对 sentinel-dashboard 二次开发,支持配置持久化
1390 0
不改一行源码,实现 sentinel-dashboard 所有配置支持 apollo 持久化
|
搜索推荐 数据挖掘 PyTorch
Py之albumentations:albumentations库函数的简介、安装、使用方法之详细攻略续篇
Py之albumentations:albumentations库函数的简介、安装、使用方法之详细攻略续篇
Py之albumentations:albumentations库函数的简介、安装、使用方法之详细攻略续篇
|
监控 前端开发 搜索推荐
EventBridge EDA (事件驱动):架构场景实践(一)|学习笔记
快速学习 EventBridge EDA (事件驱动):架构场景实践
578 0
EventBridge EDA (事件驱动):架构场景实践(一)|学习笔记
|
持续交付
《必致(BizDevOps)白皮书2022》——03必致(BizDevOps)实践体系——3.2 协作和管理领域的实践(上)
《必致(BizDevOps)白皮书2022》——03必致(BizDevOps)实践体系——3.2 协作和管理领域的实践(上)
609 0
|
存储
HashMap HashTable ConcurrentMap 中key value是否可以为null
HashMap HashTable ConcurrentMap 中key value是否可以为null
219 0