5.装饰模式 Decorator (单一职责)

结合:
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: 开始点射