浅谈设计模式-装饰器模式

书接上回,本篇讲一下结构型模式-装饰器设计模式

装饰器设计模式

定义:在不改变原有对象的基础上,将动态的将功能附加到对象上。

延伸:区别于继承,它是通过装饰对象对原有对象做功能增强,属于动态组合。

UML图

Component:组件,是一个接口,定义要被装饰的方法/逻辑

ConcreteComponent:具体组件,是一个类,实现Component接口,原始类,即将要被装饰的类

Decorator:装饰器,一个抽象父类,实现了Component接口,持有一个Component属性,即被装饰对象-ConcreteComponent

ConcreteDecoratorA/B:装饰器子类,继承Decorator,实现/拓展装饰器各种装饰功能,这些功能最终都会叠加到被装饰对象-ConcreteComponent中

上面理论,刚接触者可能有理解,又有点模糊,不急上代码。

案例分析

需求:设计大宝剑攻击属性升级
基础:大宝剑,攻击属性:100
一次锻造:金晶石,攻击+10
二次锻造:木晶石,攻击+10
三次锻造:水晶石,攻击+10
四次锻造:火晶石,攻击+10
五次锻造:土晶石,攻击+10

剑类

//剑-扮演角色-Component
//定义2个方法:武器描述,攻击总值
public interface ISword {
    //武器描述
    String desc();
    //攻击总值
    int attackValue();
}

大宝剑

//大宝剑
public class BigSword implements ISword{
    @Override
    public String desc() {
        return "大宝剑";
    }
    @Override
    public int attackValue() {
        //基本属性100
        return 100;
    }
}

晶石装饰器

//晶石装饰器-对应Decorator
public   class CrystalDecorator implements ISword{
    private ISword sword;  //被装饰对象
    public CrystalDecorator(ISword sword) {
        this.sword = sword;
    }
    @Override
    public String desc() {
        return sword.desc() + "\n";
    }
    @Override
    public int attackValue() {
        return sword.attackValue();
    }
}

金晶石

//金晶石装饰器
public class GoldCrystalDecorator extends CrystalDecorator{
    public GoldCrystalDecorator(ISword sword) {
        super(sword);
    }

    @Override
    public String desc() {
        return super.desc() + " 融入金晶石,攻击+10";
    }

    @Override
    public int attackValue() {
        return super.attackValue() + 10;
    }
}

木晶石

//木晶石装饰器
public class WoodCrystalDecorator extends CrystalDecorator{
    public WoodCrystalDecorator(ISword sword) {
        super(sword);
    }

    @Override
    public String desc() {
        return super.desc() + " 融入木晶石,攻击+10";
    }

    @Override
    public int attackValue() {
        return super.attackValue() + 10;
    }
}

水晶石

//水晶石装饰器
public class WaterCrystalDecorator extends CrystalDecorator{
    public WaterCrystalDecorator(ISword sword) {
        super(sword);
    }

    @Override
    public String desc() {
        return super.desc() + " 融入水晶石,攻击+10";
    }

    @Override
    public int attackValue() {
        return super.attackValue() + 10;
    }
}

火晶石

//火晶石装饰器-对应ConcreteDecorator
public class FireCrystalDecorator extends CrystalDecorator{
    public FireCrystalDecorator(ISword sword) {
        super(sword);
    }

    @Override
    public String desc() {
        return super.desc() + " 融入火晶石,攻击+10";
    }

    @Override
    public int attackValue() {
        return super.attackValue() + 10;
    }
}

土晶石

//土晶石装饰器
public class SoilCrystalDecorator extends CrystalDecorator{
    public SoilCrystalDecorator(ISword sword) {
        super(sword);
    }

    @Override
    public String desc() {
        return super.desc() + " 融入土晶石,攻击+10";
    }

    @Override
    public int attackValue() {
        return super.attackValue() + 10;
    }
}

测试

public class App {
    public static void main(String[] args) {
        //大宝剑
        ISword sword = new BigSword();
        System.out.println("名称:" + sword.desc());
        System.out.println("攻击值:" + sword.attackValue());

        System.out.println("---------开始装饰---------");
        sword = new GoldCrystalDecorator(sword);    //金
        sword = new WoodCrystalDecorator(sword);    //木
        sword = new WaterCrystalDecorator(sword);   //水
        sword = new SoilCrystalDecorator(sword);    //火
        sword = new FireCrystalDecorator(sword);    //土

        System.out.println("名称:" + sword.desc());
        System.out.println("攻击值:" + sword.attackValue());

    }
}

UML

 解析

BigSword:就是被装饰的对象,已经有基本操作:desc/attackValue

GoldCrystalDecorator等:金木水火土装饰器对原先对象BigSword基本操作进行功能附加。

调用时直接使用BigSword desc/attackValue方法即可实现基本 + 附加功能

适用场景

1>扩展一个类的功能或者给一个类添加附加功能,可用
2>动态给一个对象添加功能,同时要求功能可以动态撤销,可用

优缺点

优点
继承功能补充,比继承更灵活,不改变原有对象的情况下给对象一个扩展功能,实现动态扩展
通过使用不同的装饰类以及这些装饰类的排列组合,可以实现不同效果
符合开闭原则

缺点
类结构有点多,会增加程序复杂性
当动态装饰时,多层装饰时会更复杂

VS继承

装饰器模式实现比继承更灵活

被装饰对象(BigSword)与装饰器(GoldCrystalDecorator)分离,可以根据业务需要动态添加装饰逻辑,可加,可卸载。

如果采用继承方式被修饰对象与装饰器紧耦合,就无法动态剥离了。

VS AOP

装饰模器式跟AOP在思想设计上是一致的、

AOP:面向切面编程,是一种编程范式,功能也是在不改动源码前提上,动态增加功能。

那跟装饰器模式区别在哪?

装饰器模式需要叠加额外功能, 需要主动调用装饰器,对原对象进行装饰,属于主动

AOP实现更加灵活,更加可配置,基本上跟源码没有耦合,额外功能添加是被动添加,不需要原对象做任何操作,AOP主动织入,很多情况都是原对象不知情情况下织入的。

开发案例

装饰器模式在开发用得非常多举几个例子

JDK-BufferedInputStream

File file = new File("c:/aa.txt");
FileInputStream fin = new FileInputStream(file);
BufferedInputStream bin = new BufferedInputStream(fin );
bin.read();
public class BufferedInputStream extends FilterInputStream {
    public BufferedInputStream(InputStream in) {
        this(in, DEFAULT_BUFFER_SIZE);
    }

    public BufferedInputStream(InputStream in, int size) {
        super(in);
        if (size <= 0) {
            throw new IllegalArgumentException("Buffer size <= 0");
        }
        buf = new byte[size];
    }

}

public class FilterInputStream extends InputStream {

    protected volatile InputStream in;


    protected FilterInputStream(InputStream in) {
        this.in = in;
    }

}

UML

 从上看

InputStream--对应---Component

FileInputStream-对应---ConcreteComponent

FilterInputStream---对应---Decorator

BufferedInputStream--对应--ConcreteDecoratorA

Mybatis-Cache

Cache

public interface Cache {
 
  String getId();
  void putObject(Object key, Object value);
  Object getObject(Object key);

}

PerpetualCache 

public class PerpetualCache implements Cache {

  private final String id;

  private Map<Object, Object> cache = new HashMap<>();

  public PerpetualCache(String id) {
    this.id = id;
  }

  @Override
  public String getId() {
    return id;
  }

  @Override
  public int getSize() {
    return cache.size();
  }

  @Override
  public void putObject(Object key, Object value) {
    cache.put(key, value);
  }

}

 LruCache 

里面的delegate就是被装饰对象

public class LruCache implements Cache {

  //被装饰对象
  private final Cache delegate;
  private Map<Object, Object> keyMap;
  private Object eldestKey;

  public LruCache(Cache delegate) {
    this.delegate = delegate;
    setSize(1024);
  }

  @Override
  public String getId() {
    return delegate.getId();
  }

  @Override
  public int getSize() {
    return delegate.getSize();
  }
}

Cache---对应---Component

PerpetualCache -对应---ConcreteComponent

没有---对应---Decorator

LruCache --对应--ConcreteDecoratorA

总结

装饰器模式本质:动态组合

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

浪飞yes

我对钱没兴趣~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值