结合:
Android设计模式 006 装饰者模式  【B站】对整个重构的细节讲的容易懂
Android的设计模式-装饰者模式   【简书】结合安卓源码讲的还可以,让我对context有更深入的理解


1.模式定义
    动态(组合)地给一个对象增加一些额外的职责。就增加功能而言,Decorator模式比生成子类(继承)更为灵活(消除重复代码&减少子类个数)。--《设计模式》GoF

2.动机

  • 在某些情况下我们可能会“过度地使用继承来扩展对象的功能”,由于继承为类型引入的静态特质,使得这种扩展方式缺乏灵活性;并且随着子类的增多(扩展功能的增多),各种子类的组合(扩展功能的组合)会导致更多子类的膨胀。
  • 如何使“对象功能的扩展”能够根据需要来动态地实现?同时避免“扩展功能的增多”带来的子类膨胀问题?从而使得任何“功能扩展变化”所导致的影响降为最低?

3.要点总结

  • 通过采用组合而非继承的手法,Decorator模式实现了在运行时动态扩展对象功能的能力,而且可以根据需要扩展多个功能。避免了使用继承带来的“灵活性差”和“多子类衍生问题”。
  • Decorator类在接口上表现为is-a Component的继承关系(继承+组合),即Decorator类继承了Component类所具有的接口。但在实现上又表现为has-a Component的组合关系,即Decorator类又使用了另外一个Component类。
  • Decorator模式的目的并非解决“多子类衍生的多继承”问题,Decorator模式应用的要点在于解决“主体类在多个方向上扩展功能”--是为“装饰”的含义。

4.uml类图

5.实现

以绝地求生中枪械为例

5.1抽象枪械

public abstract class Gun {
public abstract void load();//装子弹 public abstract void fire();//发射子弹
}

5.2具体枪械

98k 和m416
public class Gun98K extends Gun {
@Override
public void load() {
Log.e("Gun98K", "装满5发子弹");
} @Override
public void fire() {
Log.e("Gun98K", "开始点射");
}
}
public class GunM416 extends Gun {

    @Override
public void load() {
Log.e("GunM416", "装子弹");
} @Override
public void fire() {
Log.e("GunM416", "开始扫射");
}
}

5.3抽象装饰器

public abstract class GunDecorator extends Gun {
Gun gun; public GunDecorator(Gun gun) {
this.gun = gun;
} @Override
public void load() {
gun.load();
} @Override
public void fire() {
gun.fire();
}
}

5.4具体装饰器

/**
* Describe: 加枪托
*/
public class ButtGunDecorator extends GunDecorator {
String butt; public ButtGunDecorator(Gun gun, String butt) {
super(gun);
this.butt = butt;
} @Override
public void load() {
gun.load();
} @Override
public void fire() {
Log.e("ButtGun", "降低垂直水平后坐力");
gun.fire();
}
}
/**
* Created by nbb on 2020/12/26
* Version 1.0
* Describe:子弹袋装饰
*/
public class BulletBagGunDecorator extends GunDecorator { String sight; public BulletBagGunDecorator(Gun gun, String sight) {
super(gun);
this.sight = sight;
} @Override
public void load() {
Log.e("BulletBagGunDecorator", sight + "快速");
gun.load();
} @Override
public void fire() {
gun.fire();
}
}
/**
* Created by nbb on 2020/12/26
* Version 1.0
* Describe:瞄具
*/
public class SightGunDecorator extends GunDecorator { String sight; public SightGunDecorator(Gun gun, String sight) {
super(gun);
this.sight = sight;
} @Override
public void load() {
gun.load();
} @Override
public void fire() {
Log.e("SightGun", sight + "打开 放大目标");
gun.fire();
}
}

5.5测试

  	Gun m416 = new GunM416();//捡到一把M4
Gun sightM416 = new SightGunDecorator(m416, "4倍镜");//捡到一个4倍镜
Gun buttSightM416 = new ButtGunDecorator(sightM416, "M416枪托");//捡到一个枪托 buttSightM416.load();
buttSightM416.fire(); //捡到一把满配98K
Gun gun98k = new SightGunDecorator(new BulletBagGunDecorator(new Gun98K(),
"98k子弹袋"),"8倍镜");
gun98k.load();
gun98k.fire();
//结果
// GunM416: 装子弹
// ButtGun: 降低垂直水平后坐力
// SightGun: 4倍镜打开 放大目标
// GunM416: 开始扫射 // BulletBagGunDecorator: 98k子弹袋快速
// Gun98K: 装满5发子弹
// SightGun: 8倍镜打开 放大目标
// Gun98K: 开始点射



最新文章

  1. WPF中的动画——(三)时间线(TimeLine)
  2. Mac os x下配置nginx + php
  3. git Submodule
  4. Hibernate day02笔记
  5. Linux Tomcat 简介
  6. 获取验证码,60秒倒计时js
  7. mysql show processlist命令 详解
  8. 如何优化 Java 性能?
  9. Java栈实现
  10. ASP.NET中Cookie的使用
  11. 设计模式之(二)Adapter模式
  12. Android开源项目pulltorefresh分析与简单使用
  13. CSS判断不同分辨率显示不同宽度布局CSS3技术支持IE6到IE8
  14. Rabbitmq无法监听后续消息
  15. ngRoute路径出现#!#解决方案
  16. Asp.Net进程外Session(状态服务器Session、数据库Session)
  17. DesigningFormsinAccess2010
  18. css变量使用
  19. Flink神秘工具lib
  20. <<架构漫谈>>读后感

热门文章

  1. CCF-CSP认证 C++题解目录
  2. 深入浅出之mysql索引--上
  3. AgileConfig-轻量级配置中心 1.1.0 发布,支持应用间配置继承
  4. VUE:data数据中,能被网页渲染出来的数据类型有哪些
  5. MongoDB 分片集群配置
  6. 02day
  7. 第8.1节 Python类的构造方法__init__深入剖析:语法释义
  8. 题解-CF1065E Side Transmutations
  9. docker下安装svn-server
  10. 【Azure Developer】通过Azure提供的Azue Java JDK 查询虚拟机的CPU使用率和内存使用率